Initialize a value for a shared property - vb.net

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.

Related

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.

Accessing an element of a custom type list by property value

Let's say I have a class called ControlInfo, which has the following properties:
Public Property Control As Control
Public Property ControlState As Int32
Now I want to create a method for accessing a specific instance of ControlInfo from a List, so I do this:
Public Function GetInstance(control As Control) As ControlInfo
For Each c As ControlInfo In list
If c.Control.Name = control.Name Then
Return c
End If
Next
Return Nothing
End Function
Is there a better way to access specific instance from a list of a custom class based on its property value? Is the loop approach bad for performance?
Sidenote: I have also considered the implementation of a Dictionary other than a List (so I would access an instance via a key, which can be a lot better than looping through all the values), but I feel that if I resort to that I would be avoiding a problem instead of solving it. Maybe I am being paranoid but I would like to know other valid approaches here, and be more certain of what should/shouldn't be done.
Thanks.

Serializing shared field

I have one class with a private static (shared, since I'm in VB.NET) field and its associated public static property, since it stores one variable that should be the same to all the instances of this class. So far, so good.
The problem arrives when trying to binary serialize these kind of objects, since this shared field is nos being properly stored and returns to its default value when deserializing.
I suppose this is the expected behaviour, so my question is... how can I make a shared field persistent?
I have read some comments to similar questions that say that this is a bad design, but it really makes sense (AFAIK) in my case, since this variable should be the same to all the object, but can be changed by the user and therefore should be stored.
Can you suggest another way of doing it?
Thanks!
EDIT: (sorry, I was in a hurry and couldn't complete my question until now)
My Class looks like this:
Public MustInherit Class NitrogenController
Private _active As Boolean
Private Shared _controlInterval As TimeSpan
Private _lastControlTime As Date
Public Property Active() As Boolean
Public Shared Property ControlInterval() As System.TimeSpan
'other properies that must be persisted
Public Function Control() As Boolean
If Not Now > _lastControlTime.Add(_controlInterval) Or Not _active Then
Return False
Else
DoControl()
_lastControlTime = Now
Return True
End If
End Function
End Class
So, the problem is that I can have several nitrogen controllers, but they should all have the same _controlInterval. That's the reason why I used a shared variable for this. But it does not preserve its value after serialization/deserialization. So... any ideas about how to do this?
Thanks!

Is it possible to declare a local/class instance member reference variable in VB.net to read/update same object referred by another variable

In C++, it is possible to do:
int x;
int& foo = x;
// foo is now a reference to x so this sets x to 56
foo = 56;
But is an equivalent possible in Visual Basic .net (VB.net)?
I am aware of the ByRef term in VB.net but I have only seen (and by extensive research) this in passing parameters by reference to functions/subroutines, so that the function modifies the same variable declared by the calling code.
But I haven't seen ByRef used to declare variables (as class members or local variables). I have tried to use ByRef to do such a declaration but I get compiler errors for each ordering of the declaration I try.
The reason why I want to do this is because I want a class instance to be able to refer to a variable declared in another class instance.
Specifically, I am working on some existing VB.net code where program logic is mixed up with UI logic in VB.net form classes. I want to separate the program logic out of the form code so that it can be more easily reused. To do this I need the program logic code to be able to 'talk' to the form code so I need access to its variables.
I am using Visual Studio 2010 Express with VB.net and would prefer to remain within this environment even though I am aware that full Visual Studio has extended capabilities.
Pointers exist but they're called object references
(Now other posters, please don't quibble with me about the actual differences here. I am talking about the high level task the OP wants to accomplish)
Obviously you can't do literally what you've said - that is, surgically manipulate one member. But if you have control of the code, you can do almost as well. And from what you describe is your problem, this method will be much better, as you can pass references to an object that has many members you wish to update, instead of having to pass many individual pointers.
First define a class:
Class MyScreenValues
' Properties will work... using public fields for brevity
Public TextBox1Value as String
Public SpinControl1Value as Integer
public CheckBox1Value as Boolean
End Class
Now the equivalent of the code you posted:
Dim x as new MyScreenValues 'int x;
dim foo as MyScreenValues = x 'int& foo = x;
'// c++: foo is now a reference to x so this sets x to 56
'// .net: foo is now a reference to x so this sets x.SpinControl1Value to 56
foo.SpinControl1Value = 56;
If what you're doing is trying to pass pointers to, say, every control on your form's value to a sub, like so:
Button1_Click(...
Dim MyObject as new BusinessObject
MyObject.DoSubmit(TextBox1.Text, SpinButton1.Value, CheckBox1.Checked)
You can use the method provided by superbDeveloper, and use the ByRef keyword on the definition of the DoSubmit Sub:
Public Sub DoSubmit(ByRef Name as String, ByRef Age as Integer, ByRef Employed as boolean)
... business logic...
However this just gives you a 2-layer separation. Look into MVP, MVC, etc - however consider submitting the entire view worth of data. It's a lot of research you you may settle with what you have now. For example your business logic will be firing events on the form as it changes the form values (well, actually, they won't fire until the sub exits, due to the way VB deals with byref properties [=temp variable], but it needs to be considered).
You can also map an object's properties to a Form's properties with other libraries. Check out VALUE INJECTOR on the web. It can take a webform/winform and maybe even a WPF form and map the control values to and from an object you have predefined. Excellent for complete separation.
Hi well not sure about VB.NET but I know how do it in C#, therefore I did the solution in C# and then i used a C# to VB.NET convertor to get the VB.NET code. maybe it might help you:
http://www.developerfusion.com/tools/convert/csharp-to-vb/
C# Code
protected void TestFoo()
{
string strFooA = string.Empty;
GetFoo(ref strFooA);
Response.Write(strFooA);
}
private void GetFoo(ref string strFooA)
{
strFooA = "FooA";
}
VB.NET converted
Protected Sub TestFoo()
Dim strFooA As String = String.Empty
GetFoo(strFooA)
Response.Write(strFooA)
End Sub
Private Sub GetFoo(ByRef strFooA As String)
strFooA = "FooA"
End Sub
Pointers don't exist in the .NET framework like they do in C/C++, so you won't be able to directly achieve what you want.
There are some possible solutions on this SO page
See #NathanW answer on there:
If you are using VB the only thing that is really close to a pointer is a IntPtr. If you have access to C# you can use unsafe C# code to do pointer work.
In Addition
If you want to be able to use references then you can achieve this by using a class:
Private Class RefClass
Public x As Integer
End Class
Then you can reference one from the other:
Dim bar As New RefClass
Dim foo As RefClass = bar
bar.x = 45
Debug.WriteLine(bar.x) 'outputs 45
Debug.WriteLine(foo.x) 'outputs 45
You may already know enough to get the job done from the info at http://www.dreamincode.net/forums/topic/135354-reference-types-value-types-byval-byref/ ; however, your remark "ByRef is not required in declaration of local variables (and possibly class variables)" left me wondering if there's some confusion here.
For starters, the C++ example above, int x; int& foo = x; confuses what is meant by a "reference". My C++ isn't very strong, but, semantically speaking, I believe this C++ reference operates more like an aliasing mechanism. In VB (and C#) a reference operates like an identification code that locates an instance of a class in memory. Neither VB or C# has anything like the C++ reference type.
By now, you probably already know you can pass in your Form as a ByVal parameter, and change its properties and fields without problem. (ByVal is the default in VB.NET, so you don't even need to use it - in VB6 ByRef was the default.) If you're happy enough, you can skip the rest. But, yeah, in the case of .NET Reference variables, assuming:
Dim objA as New MyClass()
Dim objB as MyClass = objA
Then objA and objB both reference the very same instance of MyClass. You can modify via objA and objB, and you can read back from either objA or objB, because they each affect the very same instance. You can pass either objA or objB into some subroutine Foo with parameter objC As Object passed ByVal (i.e. Sub Foo(ByVal objC As Object) ) and Foo can then modify that same instance too.
The ByRef of VB and the ref of C# indicate a modifiable parameter, which means some "identification code" reference is passed instead of a value. Yet this ByVal vs. ByRef thing is clear as mud because in .NET there is a distinction made between "Value" types and "Reference" types that confuses many on whether a ByRef or ref is needed or not.
Visual Basic and C# dichotomizes variables (and data types) into two species: the "Value" (or "Structure"), and the "Reference" (or "Class").
The "Value" type means an actual collection of bits that represents an Integer, or a Boolean, or even a bitmap, or some other kind of object. In old school parlance, this is the "image" of the instantiation of an object. It is the state space of the object. It is what makes an object essentially itself, independent of where in memory it may be.
The "Reference" type means a code (which might look like an integer or a pointer) that somehow indicates the data type of the object and where in memory it resides. The computer will interpret a "Reference" to obtain the actual image of the object (i.e. its "Value").
When a "Value" parameter is passed ByVal, that means a new object is created that is in the identical image of the original expression being passed, and it is upon this copy that the function or method operates. The original image of the "Value" cannot be affected.
When a "Value" parameter is passed ByRef, that means a new "Reference" variable is created, and that "Reference" variable will contain the information that will interpret back to the image of the original "Value". Now the original image of the "Value" can be changed.
When a "Reference" parameter is passed ByVal, its "identification code", which gets interpreted back to the actual image of the object, gets copied. It is upon this copy of the code that the function or subroutine or method operates. This copy still points to the actual image of the object. Which means that an object of a Reference variable that is passed by ByVal can still have its image (i.e. its "Value") changed. However, the code of the original "Reference" itself cannot be changed.
(Note that the String type is an odd duck: It will behave as if it were a "Value" parameter even though it is in fact a "Reference" type. Hence a String passed ByVal will not be affected in the same way any other class would. Actually, String is an example of an immutable type - which means that steps are taken to prevent changes to its "Value".)
When a "Reference" parameter is passed ByRef, one now has created a new "Reference" object that points to the original "Reference" object (that, in turn, points to the "Value" of some other object via its "identification code"). The use of ByRef on a "Reference" allows one to modify (or create anew) the "identification code" of the original "Reference" object being passed as a parameter. A function or subroutine or method that performs a swap operation will use ByRef on "Reference" parameters.

Is there a way to Overload a Property in .NET

I've done plenty of Method Overloading, but now I have an instance where I would like to Overload a Property. The IDE in Visual Studio seems to allow it, since I can actually set up the two overloads, but I get an error saying it is not valid because they only differ in type. I think I'm missing something in my syntax?
I want to be able to use two (or more) different custom classes as the Type for my property.
Public Overloads Property myFlexibleProperty() As myCustomClass1
Get
Return _myFlexibleProperty1
End Get
Set(ByVal value As myCustomClass1)
_myFlexibleProperty1 = value
End Set
End Property
Public Overloads Property myFlexibleProperty() As myCustomClass2
Get
Return _myFlexibleProperty2
End Get
Set(ByVal value As myCustomClass2)
_myFlexibleProperty2 = value
End Set
End Property
All of the help I have found so far has been concerning Overloading Methods. Despite what the IDE is letting me do, I'm beginning to think this is not possible?
To overload something--method or property--you need for it to accept a different set of parameters. Since properties in VB.NET can accept parameters, I guess you can overload them; but they have to be different.
So you could do this:
Public Overloads Readonly Property Average() As Double
Public Overloads Readonly Property Average(ByVal startIndex As Integer) As Double
But not this:
Public Overloads Readonly Property Average() As Double
Public Overloads Readonly Property Average() As Decimal
This should not be possible. You are effectively trying to make a property that could return two different types. There is no way for the system to make the determination as to what you are trying to call.
You will have to give unique property names to each.
Your signatures are the same (only the return types differ). the compiler will not know which method you're calling. That is your problem. Change the signatures.
have you tried using a class based on an interface? Then, you could have different classes based on the same common interface and the property associated to the interface type, not the specific class itself.
There is one way
Public Enum myType
inInteger = 0
inDouble = 1
inString = 2
End Enum
Public Class clsTest
Dim _Value1 As Integer
Dim _Value2 As Double
Dim _Value3 As String
Public Property MyValue(ByVal Typ As myType) As Object
Get
Select Case Typ
Case myType.inDouble
Return _Value2
Case myType.inInteger
Return _Value1
Case Else
Return _Value3
End Select
End Get
Set(ByVal value As Object)
Select Case Typ
Case myType.inDouble
_Value2 = value
Case myType.inInteger
_Value1 = value
Case Else
_Value3 = value
End Select
End Set
End Property
End Class
It is not possible to overload properties. That being said, you could accomplish what you want by creating implicit conversions or overloading the = operator.
It would be possible to have the property operate on some special class, which supports widening conversion operators to and from the real types of interest. In some circumstances this could work reasonably well and provide a useful expansion. The biggest limitations:
If the special class/struct gets converted to type Object, it won't behave like the thing to which it's supposed to be typecast.
If the special thing is a class, then every time the property is get or set will require the instantiation of a new garbage-collected object.
Still, in some circumstances this may be a useful abstraction (especially if the base type would be a struct).