Advantages of Properties in Classes - vb.net

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.

Related

How to Build a List of Form Controls Before the Form is Loaded

I’m new to OOP and VB.NET, so please bear with me.
In VB.Net I currently have working code that defines, for each form, significant information about selected controls on the form.
I have defined in a public class:
Public Class FormFld
Public Property ScrField As Control ' A control on the form
Public Property DbField As String ' Its corresponding field name in the database
… ' Other info about the control or its database field
End Class
When each form loads, I create a list of FormFlds for the form’s selected controls:
At the start of each form
ReadOnly FormFlds As New List(Of FormFld)()
and in the form’s Load routine
FormFlds.Add(New FormFld With {.ScrField = Control1Name, .DbField = "Field1Name", …})
FormFlds.Add(New FormFld With {.ScrField = Control2Name, .DbField = "Field2Name", …})
…
This technique has worked well to easily loop through the selected fields and, on input, populate those fields from the database, or, on output, write those field values to the database.
With this implementation, however, the list must be built every single time the form is loaded. I’m wondering if the setup of the list can be done only once, during program initialization, before the forms are loaded.
Here’s the latest that I have tried.
In Class1:
Public Class indiv
Public FormFlds As List(Of FormFld)() ' The list for the frmIndividual form
End Class
In Module1, I attempt defining the FormFlds for the eventual form frmIndividual, to be saved as Indiv.FormFlds. I’d like the form name (f) and the list owner (owner) to be defineable so I can easily change those for each form.
Dim owner As New indiv
Dim f As FrmIndividual
owner.FormFlds.Add(New FormFld With {.ScrField = f.TxtKey, .DbField = "Sort_Key", …})
In Visual Studio, the third line shows error “BC30456: 'Add' is not a member of 'List(Of FormFld)()”.
Wondering if the problem might be due to not having an actual form FrmIndividual created yet, I tried changing the second line to
Dim f As New FrmIndividual
but it didn’t change anything.
I’m using VS 2022, v17.2.1. If there’s more info you need, please let me know.
The reason that you're told there's no Add method is because arrays have no Add method and you have an array. Here:
ReadOnly FormFlds As New List(Of FormFld)()
You are using the New keyword to invoke a constructor, so the parentheses at the end are for the argument list for that method call. Here:
Public FormFlds As List(Of FormFld)()
there's no New keyword so there's no constructor, so the parentheses at the end indicate that the field is an array type. That code is functionally equivalent to this:
Public FormFlds() As List(Of FormFld)
When you get that field you're getting a reference to an array of List(Of FormFld), not just a single List(Of FormFld) object. Of course, the field is initially Nothing anyway, so you'd have to assign something to it first to be able to use it.
By the way, the error message was already telling you what the issue was:
'Add' is not a member of 'List(Of FormFld)()`
It is telling you that Add is not a member of array of List(Of FormFld), which it's obviously not.

Why to use GET & SET methods while defining properties in VB.Net?

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.

Dynamic objects or properties?

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

vb.net get local resource name from control property

How can i get the name of a local resource that has been assigned to a control property like BackgroundImage?
For example, i have a button and i have set the BackgroundImage property to a local resource image.
What i want, is at runtime to get the name of the local resource that has been assigned to BackgroundImage of that button.
If you look at your image:
you can see two things about the way your resources are handled. First, the return is a Bitmap, so once assigned to a button or whatever, you would have a very hard time determining what it is from the image data. The second thing is that the identifiers are actually Properties not just tokens or keys into a collection. The IDE generates these in your Resources.Designer.vb file to provide access to the various resources. Here is the interface to get the bitmap of the French Flag from the resource designer file:
Friend ReadOnly Property FRFlag() As System.Drawing.Bitmap
Get
Dim obj As Object = ResourceManager.GetObject("FRFlag", resourceCulture)
Return CType(obj,System.Drawing.Bitmap)
End Get
End Property
Yours will have things like Property error_button24BUTTON_DISABLED. Like any other property, the name of the property is not part of the return, just the data associated with them.
Since what really matters is the state of the button, not the image being shown, and that Enabled state is very easy to evaluate, not much is lost just using an if statement:
If thisButton.Enabled Then
thisButton.BackGroundImage = My.Resources...
Else
thisButton.BackGroundImage = My.Resources...
End If
You would have had to do something like this to convert "True" for Enabled to "BUTTON_ENABLED" to create the resource "key" if it actually worked the way you thought it did, or was intent on getting it via Reflection.
There are several alternatives. One might be to write an ExtenderProvider to provide various state images for the controls you are working with, subclass them or just use a local Dictionary/HashTable like an Extender would:
Friend Class ButtonImages
' ToDo: load these from My.Resources in the ctor for a given button
' ...
Private Property EnabledImage
Private Property DisabledImage
Public Function GetStateImage(b As Boolean) As Bitmap
If b Then
Return EnabledImage
Else
Return DisabledImage
End If
End Function
End Class
Private myBtnImgs As New Dictionary(of Button, ButtonImages)
thisButton.BackgroundImage = myBtnImgs(thisButton).GetStateImage(thisButton.Enabled)
It is more involved than a simple If statement, but comes close to what you seem to have been looking for.

Should I create individual properties in a class or just a method to set the values?

I am learning vb.net and I am having trouble wrapping my head around the following...
I can create several properties of a custom class and get/set values or I can create a method to set them all at once. If each property is going to allow read and write should I just make a method to assign values all at once? I assume that I am missing a very important piece here. Example:
I can create 2 properties:
Public Class Employee
Public Property LastName as string
Get
Return strLastName
End get
Set(ByVal value as string)
strLastName= value
End Set
End Property
Public Property FirstName as string
Get
Return strFirstName
End get
Set(ByVal value as string)
strFirstName= value
End Set
End Property
End Class
or I can create a method:
Public Class Employee
Public Sub AddEmployee(ByVal strLastName, ByVal strFirstName)
LastName = strLastName
FirstName = strFirstName
End Sub
End Class
I apologize for such a noob question, but any insight is greatly appreciated. thank you!
If you only have a single method, you will have to use it even if you only want to change the value of a single field.
Additionally, in such a method, if you need to validate the input, you will need to write quite a lot of code for validation that is not relevant to all of the fields.
If values must be updated together, use a method to update them together and do not provide setters.
The reality of things is that how to do this depends on what you are modelling in your class. There are no hard and fast rules that say that properties are better than methods or vice versa.
There is no reason not to support both properties and a method that sets multiple properties.
Commonly, a constructor is used to create an instance of the class and to set some properties. In VB, naming a class method "New" defines it as a constructor. In your example, if you rename your AddEmployeee method to New, you will have a perfectly fine constructor. Then you program can create new instances as such:
Dim emp1 as New Employee("Burdell", "George")