I found several sources explaining to use Item[] as the property name in the PropertyChangedEventArgs for an indexed property called Item.
But what do I have to use in VB.net? Is it Item() or is it Item[] as well?
You have to use Item[], but note that an indexed property called Item does not make sense in a C# context.
If you want your VB.net code be consumed by C# code you should only use one indexed property in a class, make sure to add the Default keyword, and just return System.Windows.Data.Binding.IndexerName:
Used as the PropertyName of PropertyChangedEventArgs to indicate that an indexer property has changed.
(which just happens to be Item[]).
In C# you can't have named indexed properties like in VB.Net, e.g. something like
Default Public Property Foo(ByVal x As Integer) As Integer
...
End Property
Public Property Bar(ByVal x As Integer) As Integer
...
End Property
is not possible in C# (but you can have multiple indexers with different signatures).
Related
I am bit confused over the need to use GET & SET methods in VB.net. I want to discuss two cases in this connection: firstly when we declare the property as PUBLIC and next when we declare the property as PRIVATE.
What is I find is when I define a property as public I can directly set and access the values of that property without using the GET/SET methods --- quite simple: See below
Module Program
Sub Main()
Dim t As New test()
t.name = "Roy" 'Label 1
Console.WriteLine("t.name = {0}", t.name)
Console.ReadLine()
End Sub
End Module
Class test
Public Property name() As String
End Class
When I declare that same property as private, as shown below, I can still set and access the value of private property by simply using a constructor and a public subroutine. See below:
Module Program
Sub Main()
Dim t As New test()
t.printValue()
Console.ReadLine()
End Sub
End Module
Class test
Private Property Name() As String
Sub New()
Name = "Roy" 'Label 2
End Sub
Public Sub printValue()
Console.WriteLine("Value stored in NAME is: {0}", Name)
End Sub
End Class
So my question is why at all do we need to use the GET/SET methods? I understand that whenever an assignment happens to a property the SET method is implicitly called...but can you please help me understand cases where we MUST explicitly use the GET/SET methods? Or it is that using GET/SET is more of a choice? Validation is one thing that can be added easily at a later stage if one uses GET/SET but then is that the only reason? PLs give your views.
Also, I came across the following two related questions in stackoverflow (for different languages though): Links below:
Why to use getter and setter methods to set class properties?
Why use getters and setters/accessors?
But i could not understand most of the reasons justifying the usage of the GET/SET methods. For example if we dont use the GET/SET method then we are exposing the property to the outside world - meaning it can be directly accessed from outside the class. But then this is true only for PUBLIC properties as PRIVATE properties cannot be directly accessed from outside the class. Similarly in the second link the author mentions the following as a reason to use GET/SET: Providing a debugging interception point for when a property changes at runtime - debugging when and where a property changed to a particular value can be quite difficult without this in some languages. What exactly does this mean --- any simple real life example?
A property is a wrapper around a field, i.e., a class or struct variable. It provides a getter and/or a setter method to access this variable. (You can also have a read-only property returning the result of a simple evaluation not bound to a single field.)
The getters and setters are implicitly called when reading from, respectively writing to properties.
So, the question is not whether to use getters and setters or not, but whether to access fields directly or via a property.
You can declare a property like this, by declaring a field and writing the getter and setter explicitly.
Private _prop1 As String ' Backing field
Public Property Prop1() As String
Get
Return _prop1
End Get
Set(ByVal value As String)
_prop1 = value
End Set
End Property
or use an Auto-Implemented Property
Public Property Prop1 As String
Both declarations are equivalent. The auto-implemented property implicitly declares a backing field and implements the getter and the setter accordingly.
It can make sense to declare a property as private when you use it only inside the class where it is declared. This still provides the advantages described in the links you provided because this property still hides the details of accessing a field, does validations, etc.; however, it does not forbid the direct access to the backing field inside the class. So, you need to be more disciplined with private properties.
What does a property mean for debugging? You can easily set a breakpoint inside a getter or setter to detect accesses to a property. You cannot set a breakpoint on a field because a field is never executed. It is just a declaration.
You can also add a System.Diagnostics.Debug.Writeline("=====> test") (writes to the Output window) or do some logging in getters and setters.
See also: Tutorial: Learn to debug Visual Basic code using Visual Studio
When using Windows Forms Data Binding or WPF Data Binding properties are required. They also allow change notification.
Dynamically Calculated Values
I didn't read those links, but one reason you might want to implement your own getters & setters is that you may want to return something that requires some type of calculation or manipulation. For example, suppose you have item Sale with properties RawPrice, SalesTax, and FinalPrice. However, you need/choose to dynamically calculate the final price (based on variable sales tax) each time. So you first set the RawPrice, and then query FinalPrice, which returns RawPrice + SalesTax, but SalesTax gets dynamically calculated based on some other property like country of origin etc.
Alternate View of Data
Another reason you might want to do this is to provide another view of the same core data. For example, if your data was an HTML page, perhaps one property returns the normal string value, while another "no-HTML" Property has a custom Getter that performs some regex to remove all HTML tags and return a plain-text variation. This allows you to keep all related code inside of a sub-assembly, rather than having your main program do various manipulations.
Code Portability
This can make your life a lot easier down the road because of code portability. Your code is now more easily re-usable in other projects, since all you need is that one assembly.
Private Variables vs Properties
If I'm doing something that calls for a class with properties like that, there's good chances it's going to have methods, too. Those methods are almost always going to require creating private variables that nothing outside the assembly needs to know about. However, in such cases, they are not going to be private properties but rather simply private variables. For example, instead of Private Property Name() As String, with its implied auto-implemented backer variables with getters & setters, I would instead just say Private Name() As String, which would be equivalent to Dim Name() As String. You can use variables, constants etc. within your class just as you normally would, and, by default, the rest of the world won't know anything about them.
I'm not sure why you'd use a private Property. Maybe there's a good reason; I just don't know what it is. Most of the time, a private variable is probably what you really want. If you think there's a reason that you actually need a Private Property, I'm curious to hear your thinking on it. (I'm always open to a new way of thinking!)
History
Auto-implemented properties were not present in Visual Basic .NET for many years. In the past, you had no choice but to use GET/SET. So it's a more recent development for VB.NET to be able to simply declare a property as you do in your first code example, and for the runtime to automatically generate the backer variables.
I want to use a counter for how many objects are created from a single class, so I thought that a Shared Property would be the way to go. But, VB doesn't like that and says, "Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class"
Private _Length As Integer = 0
Public Shared Property Length As Integer
Get
Return _Length
End Get
Set(value As Integer)
_Length = value
End Set
End Property
Is there a way to initialize a shared variable, in this case to zero, and have the Property still function correctly. I used the Java get/set methodology (getLength()/setLength())and that worked fine, but I'm sure that it would be frowned up by VBers.
Also, using two variables to get/set one that is actually used seems a bit redundant. I see why it is used in the VB methodology because of the recursion that happens, but it does look strange.
The backing field _Length must also be shared.
Private Shared _Length As Integer = 0
using two variables to get/set one that is actually used seems a bit
redundant.
You don't have two variables just one which is _Length, a property just manages how you can access that variable. Note that even auto implemented properties like this use a backing-field:
Public Property Length As Int32
You just don't see it since it will be generated for you.
I apologize for the vague question, but I'm unsure how to proceed.
What I need is something that works like a class object with various fields and properties for storing data. But, since not all the fields/properties are known at the compile time, I also need to be able to add and use new fields/properties in runtime.
These objects would later be arranged in lists, sorted by the values in those fields/properties and bound to WPF controls.
For now I'm using just that: class objects with various properties, but I'm starting to run into problems, where I need to add more fields/properties.
Is there something I could use to achieve this in vb.net?
Edit:
Ok, I'll try to illustrate.
Currently I have something like this.
Let's say I have defined an object like this
Public Class DataEntry
Public Property Name As String
Public Property Type As String
Public Property Msc As Integer
End Class
That works fine if I know all the properties I will have at the start. I run into problems if I suddenly need to add another property:
Public Class DataEntry
Public Property Name As String
Public Property Type As String
Public Property Msc As Integer
Public Property AdditionalDescription As String
End Class
Of course, I could recompile the whole thing, but since I don't know all the possible properties I will be needing in the end, I was wondering, maybe there is a way to achieve this from runtime?
Or should I just use complicated heap of arrays instead of custom objects?
It's not possible to add new properties to a class during run time.
If you don't want to add properties to the class ahead of time which you might not use, then you could instead use a dictionary to store 'properties' which you're not aware of until run time.
Public Property RunTimeProperties As New Dictionary(Of String, Object)
A dictionary which holds values of type 'Object' can store just about anything. Strings, Arrays, Lists etc.
RunTimeProperties.Add("Length", 100)
RunTimeProperties.Add("Height", 200)
RunTimeProperties.Add("MiddleName", "Rupert")
RunTimeProperties.Add("SiblingsNames", New String() {"John", "Sarah", "Michael"})
You can use the TryGetValue method to get the values out of the dictionary.
Dim value As Object
If RunTimeProperties.TryGetValue("Length", value) Then
' Length was found in the dictionary
Else
' Length was not found in the dictionary
End If
I've been using classes for a while now, but I feel I may have been using them incorrectly.
When I create the properties for the class, I just use public variables so I end up with something like the following:
Class clsMyClass
Public Name As String
End Class
However, I've been reading some info on the net and they suggest that it should be set up in the following way:
Class clsMyClass
Private Name As String
Property UsersName() As String
Get
Return Name
End Get
Set(ByVal Value As String)
Name = Value
End Set
End Property
End Class
Is the way I'm doing it extremely incorrect? If so, why? I feel like the second method adds some sort of security but to be honest, it just looks like unnecessary code..?
One advantage of properties is that they let you customise the access to your private fields and enable you to do more so you can do the following (examples, it's not limited to that):
Make a property read-only for public access
Raise an even when a property is updated
Update other private fields when a property is updated
Validate the value that is being set
See below advantages of Properties over Variables from the C# in Depth article:
• There's more fine-grained access control with properties. Need it to be publicly gettable but really only want it set with protected access? No problem (from C# 2 onwards, at least).
• Want to break into the debugger whenever the value changes? Just add a breakpoint in the setter.
• Want to log all access? Just add logging to the getter.
• Properties are used for data binding; fields aren't.
Few other points:
1) You can also make properties read-only so no one from outside the class set the values but can fetch it.
2) You can do certain actions in the get and set. i.e. Append a prefix anytime set is called
3) You can also use auto-implemented property to minimize code like below:
Public Property Name As String
You are not doing anything wrong. Properties give you a shorthand basically, a syntactic sugar.
You can still use a backing private variable and do logic in get and set if you have to while using properties. Even better is the private/protected set or get, which is again another syntactic sugar so that you won't have to write all the code manually.
First of all, VB.NET allows you to use this syntax (called shorthand property declaration - I believe since VS 2010):
Public Property Name As String
Not so much different from this (called field declaration):
Public Name As String
Second, Microsoft data binding does not work well with fields. Try this example (see below).
Example. Put a listbox called ListBox1 (default name) and a button called Button1 on an empty form in an empty WinForms project. Replace your form code with this:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst As New List(Of clsMyClass)
lst.Add(New clsMyClass)
ListBox1.ValueMember = "Name"
ListBox1.DisplayMember = "Name"
ListBox1.DataSource = lst
End Sub
End Class
Class clsMyClass
Public Property Name As String = "Hello"
End Class
Start the application and notice that a listbox is populated with one entry, Hello. This proves that binding worked correctly. Now replace your property declaration with a field declaration instead. Start your application one more time and notice that a listbox is showing your class type converted to String. It means that your field binding did not work, and default binding was used instead, where DisplayMember is assigned sort of classInstance.ToString().
If you are curious to learn more about what happens behind the scenes, you can put a breakpoint on .DataSource assignment, and see how DisplayMember gets reset or keeps its value depending on whether you are using fields or properties.
I've got some classes that have properties like this, and they work perfectly because they are very normal:
Public Overridable Property CustomerLastName() As String
Get
Return m_CustomerLastName.Value
End Get
Set(ByVal Value As String)
m_CustomerLastName.Value = Value
End Set
End Property
I want to change them to work like this (and don't worry about what IField is, suffice it to say it represents a field in a table):
Public Overridable Readonly Property CustomerLastName() As IField
Get
Return m_CustomerLastName
End Get
End Property
That way, you could do Customer.CustomerLastName.PreviousValue, or Customer.CustomerLastName.IsDirty, etc.
But that doesn't bind correctly. Understandable, since databinding is supposed to be a two-way thing, and there's reflection involved, etc.
Of course it can still be a two-way street, I just need to be able to say, "Hey DataBinding! Look over here!"
So. What do I do here?
Note: Right now, all I'm trying to do is DataBind to a GridView for display purposes. But I want this to be flexible.
(Update re edit) If it is just for display purposes, you can probably just set the ToString() on the class that implements IField.
(original)
No - 2-way data binding wants either INotifyPropertyChanged, or an CustomerLastNameChanged event. You can shim this into a custom model by implementing ICustomTypeDescriptor or TypeDescriptionProvider, but then you need to write your own PropertyDescriptor implementation.
Re IsDirty - that is ShouldSerializeValue in PropertyDescriptor terms.