How to hide a public property without making it private or removing it - vb.net

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.

Related

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

Difference between a one-line ReadOnly property and a ReadOnly with explicit Get statement in 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.

Overriding a Custom Control's Text Property to use a Textbox's Text causes the Textbox to display the Control's name by default

Using VB.net (2005), I'm creating a custom control (a folder picker) that contains a textbox and button. Recently I've added the following:
<Browsable(True), DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
Public Overrides Property Text() As String
Get
Return Me.uiPath.Text
End Get
Set(ByVal value As String)
Me.uiPath.Text = value
End Set
End Property
The problem I'm having is that now when the control is created, the textbox always defaults to showing the name of the control (instead of being blank). It seems the Text property is being changed after Sub New is called, however, I've checked the designer, and I cannot see where it is doing this.
I know that changing the name of the property would resolve the issue, but I would like to know why this is happening (I'm guessing it has something to do with the standard designer?), and if there is a way to resolve (or work around) it, while still using the Text property?
I don't know if it makes any difference, but I am using a custom designer:
Public Class FolderPickerDesigner
Inherits Windows.Forms.Design.ControlDesigner
Public Overrides ReadOnly Property SnapLines() As IList
Get
Dim SnapLinesList As ArrayList = TryCast(MyBase.SnapLines, ArrayList)
If (Me.Control IsNot Nothing) AndAlso (Me.Control IsNot Nothing) Then
Dim FP As FolderPicker = CType(Me.Control, FolderPicker)
SnapLinesList.Add(New SnapLine(SnapLineType.Baseline, FP.uiPath.Bottom - 5, SnapLinePriority.Medium))
End If
Return SnapLinesList
End Get
End Property
End Class
Any help / ideas would be appreciated. If this doesn't / can't be resolved, I'll mark the most helpful post as the answer...
Set(ByVal value As String)
If Me.DesignMode And (Environment.StackTrace.Contains("System.Windows.Forms.Design.ControlDesigner.InitializeNewComponent")) Then Return
BaseT.Text = value
End Set

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.

How to set the text of list items in Windows Forms

I am trying to figure out how to set the value of the text that is displayed for each item of a list control, such as a checkbox list, but really this applies to most list controls, not just the checklistbox control.
I have a checklistbox control,
Friend WithEvents clstTasks As System.Windows.Forms.CheckedListBox
that I usually want to populate with a list of task names. I call the add method to add a Task object to the list. I know that if I override the ToString method, whatever value is returned by that function will be displayed as the text for the list item.
However, in rare situations, I want to display something else other than just the name. For example, perhaps I want to display the name and the value of another property, such as the value of the Boolean property "Optional" shown in parenthesis following the name.
What is the best way to do this?
The best that I can think of is to define a property which is set in the GUI layer and then used by the ToString function to determine how it should behave when called. If the controlling property is set to one value, the ToString will return the Name, else it will return the Name followed by the value of the Optional flag. This seems a little disjoint a kludged to me.
The other alternative which seems a little overkill is to define a new class which inherits from Task, for example TaskOptional, which overrides the Tostring method on the base class. In this subclass, the ToString function would return the Name/Optional flag value. However, this, too, seems a little nuts to have to come up with a new class just to modify how the text is being displayed in the presentation layer. I feel that I should be able to control this in the presentation layer without changing the business object or creating a new derived object.
What is the best way to accomplish this?
For Each CurrentTask As Task In _MasterTaskList
clstTasks.Items.Add(CurrentTask, True)
Next
Public Class Task
Private _Name As String
Private _Optional As Boolean
Public Sub New (name As String, optional As Boolean)
_Name = name
End Sub
Public Overrides Function ToString() As String
Return _Name
End If
End Function
End Class
You can set the DisplayMember property of your CheckedListBox to the name of one of your custom class' property.
Let's say you create a property like the following:
Public ReadOnly Property NameOptional() As String
Return _Name & " (" & _Optional & ")"
End Property
then you can set the display member like this:
clstTasks.DisplayMember = "NameOptional"
When you set a display member, this property will be displayed instead of the ToString value.
You could do the following
Public Overrides Function ToString() As String
Return string.Format("{0}{1}", _Name, IIF(_Optional, " (Optional)", ""))
End Function
EDIT: You will have to set the value of _optional in the constructor, which is missing in the code you have provided.