Difference between a one-line ReadOnly property and a ReadOnly with explicit Get statement in vb.net - vb.net

I have a simple question.
Is there a difference between a one-line ReadOnly Property and a ReadOnly Property with an explicit Get Statement?
For example, In Visual Studio 2010 I used to have to do this:
Private _Message As String = ""
Public ReadOnly Property Message As String
Get
Return _Message
End Get
End Property
Public Sub New(Message As String)
_Message = Message
End Sub
But now here I am in Visual Studio 2015 and it let's me get away with this:
Public ReadOnly Property Message As String
Public Sub New(Message As String)
Me.Message = Message
End Sub
Now I wasn't trying to me lazy, I just ran across it, expecting IntelliSense to force the Get Statement. So I'm left wondering if there is a difference that I should be aware of. Is it bad practice or does it do something different?
I've managed to find tons of topics and forums about ReadOnly in C#, but I seem to be coming up dry when searching the topic regarding vb.net.
I'll appreciate any input.
Thanks! =)

Properties without explicit getters and setters are simply a syntactic convenience. There's no difference in implementation. You should generally use the second option because it makes your code more readable. Only use the first option if you need extra functionality in the getter.

The accepted answer appears to be untrue, at least for me in Visual Studio 2022.
When a property is not a constant, you have to use the multiline declaration otherwise the initial value is cached
This
Private ReadOnly Property ConnectionFile As String
Get
Return gsapppath & "\connection.txt"
End Get
End Property
returns the correct path whereas this
Private ReadOnly Property ConnectionFile As String = gsapppath & "\connection.txt"
did not include the path because the variable gsapppath was not initialized at the time the class was created, yet it was initialized at the time the property was fetched.
So it's not just a syntactic convenience, there is a functional difference.

Related

How to hide a public property without making it private or removing it

Premise
Suppose that we have a class in a dll with a simple public property "OldP". In a newer version of this dll, I want to change the name of this property in "NewP". I can't simply replace the property name, because this dll is used in a lot of program and I can't change them...
I want to hide this property and show only the newer property. How is this possible?
"Browsable" attempt
Before asking this, I searched similar questions on StackOverflow and read something about Browsable, but it doesn't work. Here is my code:
Public Class Example
Private _p As Integer
<System.Obsolete("Use NewP instead", False)>
<System.ComponentModel.Browsable(False)>
Public Property OldP() As Integer
Get
Return _p
End Get
Set(ByVal value As Integer)
_p = value
End Set
End Property
Public Property NewP() As Integer
Get
Return _p
End Get
Set(ByVal value As Integer)
_p = value
End Set
End Property
End Class
When I create a new Example object, I can still see "OldP":
Where I'm wrong?
You cannot completely prevent the old property from being used, but you can hide it from IntelliSense by adding this directive: <System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)>. The OldP property will no longer be suggested, but still be accessible normally.
Beside that, I recommend you change the OldP property so that it refers not to the _p object, but to the NewP property to make future management easier, so that you don't have to worry about the deprecated version in the future.

What do the Get and Set commands in Visual Basic do?

What do the Get and Set commands in Visual Basic do? I encountered the Get and Set commands in my book's chapter on Object-Oriented Programming. Here is some code:
Public Property SocSecNum() As String
Get
Return m_ssn
End Get
Set(value As String)
m_ssn = value
End Set
End Property
When you have a field, i.e. a member variable, you can get its value:
var = someObject.SomeField
or you can set its value:
someObject.SomeField = someValue
The whole point of a property is that, from the outside, it behaves just like a field but, from the inside, it behaves like methods. That means that you can get and set a property just like you can a field but, on the inside, rather than just straight assignment and retrieval, it actually executes the Get and Set part of the property definition.
When your project is compiled, they are actually implemented as methods and the property value is stored elsewhere. That might be a dedicated field or it might not. An example of the latter is the Lines property of a TextBox. The is no dedicated field for that data. What actually happens is that the Get part takes the current text, splits it on line breaks and returns the resulting array. Similarly, the Set part combines the array provided into a single String and sets the Text. Two of the most common reasons for extra code are validation and raising events.
A simple field declaration looks like this:
Public SomeField As SomeType
A fully-implemented property looks like this:
Private someField As SomeType
Public Property SomeProperty As SomeType
Get
Return someField
End Get
Set(value As SomeType)
someField = value
End Set
End Property
As you can see, the field is private and, when the property is invoked in code, the getter and setter will get or set the value of that field. Once compiled, that code actually looks like this:
Private someField As SomeType
Public Function get_SomeProperty As SomeType
Return someField
End Function
Public Sub set_SomeProperty(value As SomeType)
someField = value
End Sub
As you can see, the getter and setter are literally methods and the property is just syntactic sugar. Java doesn't have properties and Java developers literally write these two methods as accessors for a field.
More recently, the authors of VB have realised that it's laborious to write all that code out over and over for lots of properties so we now have auto-properties. You can simply write this:
Public Property SomeProperty As SomeType
and everything else is implied. There's still a backing field and there is still a getter and a setter but your code is not cluttered up by showing them. This is how you will write most properties these days. As I said before, you'll still need to write the property out in full if you want to add any extra functionality to the getter or setter. Raising a changed event is probably the most common example of that, e.g.
Public Event SomePropertyChanged As EventHandler
Private someField As SomeType
Public Property SomeProperty As SomeType
Get
Return someField
End Get
Set
If someField <> value Then
someField = value
OnSomePropertyChanged(EventArgs.Empty)
End If
End Set
End Property
Protected Overridable Sub OnSomePropertyChanged(e As EventArgs)
RaiseEvent SomePropertyChanged(Me, e)
End Sub
In this case, when the property is set, the backing field is set if and only if the new value is different to the old value and then an event is raised to notify listeners of that change in property value. The fact that properties can include extra code like this is why they should be used over fields for public data.
On the Tools menu select Options. Click on Debugging. Uncheck Step over properties and operators
Create your class thusly. It can be nested in the form class for this little test.
Public Class SomeClass
Private m_ssn As String
Public Property SocSecNum() As String
Get
Return m_ssn
End Get
Set(value As String)
m_ssn = value
End Set
End Property
End Class
Now, in the Button.Click create an instance of your class. Set the SocSecNum. Then Get the value and assign it to a text box.
Next set a break point in your code on the first line of the button code. Do this by positioning your cursor on the gray line to the left of the code and clicking.
Run your program and click the button. You will encounter the break point. You can now step through your code line by line. Use the Step into symbol.
You will see that when you set the property the Property Procedures Set is called. The value is stored in the Private m_ssn variable. Likewise, when you get the property the value of the private variable is returned. Hold your cursor over the m_ssn variable when you are in the Property Procedure and you will see the value stored there.
All this boilerplate code disappears in current versions of Visual Studio where the default Getter, Setter and private member are created for you behind the scenes with auto properties. You can still write the Get and Set and private variable when you need to do things to the input or output.
Here's a little that can give you an idea
I used this if to easily disable some buttons while process is running
and then when you call the "decrypting = false" the disabled buttons will become enabled
Dim dec As Boolean
Private Property decrypting As Boolean
Get
Return dec
End Get
Set(value As Boolean)
dec = value
partialFile = False
btnAddFiles.Enabled = Not dec
btnAddFolder.Enabled = Not dec
btnAddKeyFile.Enabled = Not dec
btnSaveAs.Enabled = Not dec
txtOutputFileName.Enabled = Not dec
txtOutputFolder.Enabled = Not dec
txtInputFilePath.Enabled = Not dec
txtKeyFilePath.Enabled = Not dec
LV.Enabled = Not dec
btnDecrypt.Enabled = Not dec
btnAbort.Enabled = dec
If Not decrypting Then
Me.Text = "TS Decrypter and Joiner v1.0"
End If
End Set
End Property

VBA - Class property with reserved keyword as the name

In VBA, is there any known mechanism to fool the compiler into allowing the use of reserved keywords as names for class properties? For example, I would like to create a property called Select in one of my class modules. However, the compiler flags my declaration as an error. Below is the syntax I used:
Public Property Get Select() As Database.SQLStatements
End Property
Database is my VBA project name and SQLStatements is one of the class modules I created. Also, I'm running the code in MS Access 2010.
You can do that and use any keyword/reserved word in your VBA. But then it will make your code a lot messy and very hard to read/debug/maintain.
If you have a bool property named If in your class you will end up with something like this If .If  Then, well, good luck reading that. Also code maintenance like Find/Replace/rename etc. will need extra caution and more work.
Anyhow, if you are willing to go through all this pain, here is how you do it.
After the keywords/reserved words add a invisible blank space using ALT+0160 and that's it. VBA will consider it a perfectly legal name. e.g. If .
Also, you will have to either use intellisense for using these propertynames or manually type the altcode everywhere. That's extra typing.
clsTest
Option Explicit
Private m_sSelect As String
Private m_bIF As Boolean
Public Property Get Select () As String '~~> Select () is actually typed as SelectALT+0160()
Select  = m_sSelect
End Property
Public Property Let Select (ByVal sNewValue As String)
m_sSelect = sNewValue
End Property
Public Property Get If () As Boolean
If  = m_bIF
End Property
Public Property Let If (ByVal bNewValue As Boolean)
m_bIF = bNewValue
End Property
Test Module
Option Explicit
Sub demo()
Dim objTestClass As clsTest
Set objTestClass = New clsTest
With objTestClass
.Select  = "It works. But it will, for sure, create readibility/maintenance issues."
.If  = False
End With
MsgBox objTestClass.Select 
'/ See how hard it will to read/debug this sort of code
With objTestClass
If .If  Then '~~> This line here :)
MsgBox "If prop value is TRUE"
Else
MsgBox "If prop value is FALSE"
End If
End With
End Sub
ALT+0160 <> Space

VB.NET Property as StringDictionary?

I'm trying to create a new property with a type of StringDictionary but when I use the property like a stringdictionary variable I am getting an error.
The goal is to NOT use a variable, I need to use a property for this. Behind the scenes I am saving the stringdictionary value to a global user-ID indexed collection. Here's the code that creates the property and attempts to get and set:
Public Property MaxLenDict As StringDictionary()
Get
Return GetFromCollection("MaxLenDict")
End Get
Set(Value As StringDictionary())
SaveToCollection("MaxLenDict", Value)
End Set
End Property
Public Sub ExampleSub()
If MaxLenDict("hello world") = "" Then MaxLenDict.Add("Hello World", "I'm Here")
End Sub
Get this error in ExampleSub "StringDictionary cannot be converted to string" in the IF statement on this code:
MaxLenDict("hello world")=""
So how do I successfully make and use a property as a stringdictionary?
Your property is of type StringDictionary() (an array!), not StringDictionary.
I’m not sure that using StringDictionary is advised in the first place, though. The class is simply a remnant from pre-generics versions of .NET. Use Dictionary(Of String, String) instead.

Dynamic properties for classes in visual basic

I am a vb.net newbie, so please bear with me. Is it possible to create properties (or attributes) for a class in visual basic (I am using Visual Basic 2005) ? All web searches for metaprogramming led me nowhere. Here is an example to clarify what I mean.
public class GenericProps
public sub new()
' ???
end sub
public sub addProp(byval propname as string)
' ???
end sub
end class
sub main()
dim gp as GenericProps = New GenericProps()
gp.addProp("foo")
gp.foo = "Bar" ' we can assume the type of the property as string for now
console.writeln("New property = " & gp.foo)
end sub
So is it possible to define the function addProp ?
Thanks!
Amit
It's not possible to modify a class at runtime with new properties1. VB.Net is a static language in the sense that it cannot modify it's defined classes at runtime. You can simulate what you're looking for though with a property bag.
Class Foo
Private _map as New Dictionary(Of String, Object)
Public Sub AddProperty(name as String, value as Object)
_map(name) = value
End Sub
Public Function GetProperty(name as String) as Object
return _map(name)
End Function
End Class
It doesn't allow direct access in the form of myFoo.Bar but you can call myFoo.GetProperty("Bar").
1 I believe it may be possible with the profiling APIs but it's likely not what you're looking for.
Came across this wondering the same thing for Visual Basic 2008.
The property bag will do me for now until I can migrate to Visual Basic 2010:
http://blogs.msdn.com/vbteam/archive/2010/01/20/fun-with-dynamic-objects-doug-rothaus.aspx
No - that's not possible. You'd need a Ruby like "method_missing" to handle the unknown .Foo call. I believe C# 4 promises to offer something along these lines.