I have often come across code that looks like this.
Public Property Get MyProperty() As String
MyProperty = m_MyProperty
End Property
Public Property Set MyProperty(ByVal value As String)
m_MyProperty = value
End Property
Or even:
Public Property Get MyProperty() As String
Return m_MyProperty
End Property
And I had never ever met with this.
Public Property Let MyProperty(ByVal value As String)
m_MyProperty = value
End Property
Is the Let keyword the same as Set ?
According to this post, it seems so.
Properties in VB
MSDN states:
Property Let Statement
Declares the name, arguments, and code that form the body of a Property Let procedure, which assigns a value to a property.
Property Set Statement
Declares the name, arguments, and code that form the body of a Property procedure, which sets a reference to an object.
In addition to it, as per MSDN definition:
Property
A named attribute of a control, field, or object that you set to define one of the object's characteristics (such as size, color, or screen location) or an aspect of its behavior (such as whether the object is hidden).
Object
Objects seen in a Microsoft Access database:
tables, queries, forms, reports, macros, and modules
objects that are defined by the system, such as the MSysObjects table
Objects seen in a Microsoft Access project:
objects stored in the Access project file: forms, reports, macros, and modules
objects stored in the Microsoft SQL Server database: tables, table properties (such as > - indexes, triggers, keys, constraints, defaults, rules, and user-defined data types), views, stored procedures, and database diagrams
objects defined by the system, such as the sysindexes table
Objects seen in both Access databases and Access projects:
data access pages, which are shortcuts (displayed in the Database window) to corresponding HTML files stored in the file system
information from another application, such as a chart (graph) or a drawing
Except that the context under which I have seen the Property Let Statement used, there is no Access or whatsoever else.
Thanks for the received comments. They guided me to MSDN, though I still can't get the meaning of the Let statement, apart that it might be interchangeable with the Set statement, as I see it.
Are they both really interchangeable?
You pretty much answered your own question.
As you can see from the MSDN docs, a Let declaration for a property is used to assign a value, i.e. to be used for any datatype except for objects (for which you would normally assign through Set anyway).
So, following the same logic, a Set declaration would be used if you want/need to be able to assign objects, and only objects (typed or not) to a property.
So, let's say you have:
Property Let MyFirstProperty(NewValue As String)
m_sMyFirstProperty = NewValue
End Property
Property Set MySecondProperty(NewValue As Object)
Set m_oMySecondProperty = NewValue
End Property
Then the following won't work:
' This won't work
MyFirstProperty = CreateObject("...")
' Neither will this
Set MyFirstProperty = CreateObject("...")
' Also, the following won't be allowed
MySecondProperty = "My new string"
But the following two statements will:
MyFirstProperty = "My new string"
Set MySecondProperty = CreateObject("...")
Note that you can have both a Let and Set declarations for the same property at the same time, depending on what you want to do:
You could handle objects being assigned to the property differently (through the Set declare) than for other datatypes (using the Let);
Or, if your internal variable for the property is a Variant, and you want to allow both objects and scalar values to be assigned to the property.
In short, then:
If you want to assign values to a property (everything but objects), add a Let handler for the property.
If you want to assign objets to a property, you'll need a Set handler for the property.
Related
I have 10 TrackBar1 TrackBar2, TrackBar3 ..... TrackBar10. What I want is how to manipulate it.
I Have problem with access to TrackBar control property Min, Max, Value ....
For i = 1 to 10
' its OK
Me.Controls("TrackBar" & i.ToString("0")).Text = "Test1"
' Error -Min is not a member "System.Windows.Forms.Control"
Me.Controls("TrackBar" & i.ToString("0")).Min = 10
Next
When you index the Controls collection, you get a Control reference back. That collection can store any type of control, so the only thing that they all have in common is that they inherit the Control class. That means that you can access any members of the Control class directly. Text is a member of the Control class so you can access the Text property directly. Any members that are more specific than that require a cast as the more specific type in order to access them. If you want to access members of the TrackBar class then you need a reference of type TrackBar rather than type Control, which means casting as that type.
Dim c = Me.Controls("TrackBar" & i)
Dim t = DirectCast(c, TrackBar)
To explain casting, I always use the example of taking a pet to the vet. A vet can treat all types of animals but, when you take your pet, it is a specific type of animal. When you present a box to the vet, all they know is that there's an animal inside, so all they know that they can do for it is the things that apply to all animals. Once you take your pet out of the box and they see what type of animal it is, they then know that they can do all the things specific to that type of animal. Your pet didn't magically change from one type to another but the vet now knows all the specific things it can do for it as well as the general.
That's how casting in programming works. Your TrackBar was always a TrackBar but, because it was initially accessed via a Control reference, the compiler only knew that it can do things with it that are common to all controls. The cast informs the compiler of the specific type so the compiler knows that it can do things with it specific to that type.
One option to avoid the explicit cast is to just get the TrackBars in the first place:
For Each tb In Me.Controls.OfType(Of TrackBar)()
'Use tb here.
Next
The OfType method will filter out all items not of the specified type and will return references of the specified type, so tb is type TrackBar in that code. You'd have to use a For Each loop in this case, so you have less control over the order the items are accessed. They will be returned in accordance with the z-order on the form. That means that if you added them in ascending numerical order, which seems likely, and did not change the z-order, you'll still get them back in ascending numerical order.
I have built a UserControl class and am exposing certain properties to the parent object.
When i drag and drop the component to the parent objects designer surface, i get the effect i need (per say). What i want to further develop is the ability to pre-fill the property value (in properties window) as a default but it isnt auto-populating as i would have expected.
Here is what i have so far:
<Browsable(True), Category("Data"),
DefaultValue("01/01/1990")>
Public Property [Date] As String
Get
Return Me._dt
End Get
Set(value As String)
Me._dt = value
dtValue.Text = value
End Set
End Property
I understand that DefaultValueAttribute assigns the value if no other assignments are made, but thought it would also place that value in the field in the Properties Window.
As well, this ultimate assignment will go up one more level as a collection, so any advise or URL's for how to make a Collection of Components available via Properties Window?
I understand that DefaultValueAttribute assigns the value if no other assignments are made
That is incorrect.
The DefaultValueAttribute is just metadata that tells the designer what the default is.
It is still up to your code to ensure that the property actually gets that value.
I have a class module in an Excel project that has a property called Marks, this is a VB Collection and has a public get property (but no set or let).
I can assign values to this without any problem:
myObject.Marks.Add 3.14159
However, when I try to do something with this object (e.g., iterating through it), I get an error:
3021: Either BOF or EOF is true or the current record has been deleted
However, if I try myObject.Marks.Count, it shows that the collection contains the amount of data that I was expecting... I just can't access it!
I don't really understand why. I am using the same process with other collection properties within the object -- even collections of collections -- and they're working fine.
Any ideas?
myObject.myCollection.Add recordset!field adds the recordset field object to the myCollection object, rather than its value. As such, simply casting the field to its appropriate type solves the problem.
I'm making a public property, and it keeps inserting a snippet of code. What is this code for? And how come it doesn't happen to my other public properties?
Specifically the snippet:
Set(value As ObjectName())
Here's the full public property code:
Public Property PropertyName() As ObjectName()
Get
Return Me.propertyName
End Get
Set(value As ObjectName())
Me.propertyName = value
End Set
End Property
When I try deleting
(value As ObjectName())
It keeps coming back. But my other properties, that snippet of code doesn't automatically generate...
When you have a property, you need a get and set (unless it is readonly).
The get part is for when other code tries to access the value of the property. The set part is for when other code tries to write the value of the property. The (value As ObjectName()) part is simply the definition of parameter expected.
It will generate for your other properties too, if you were to start typing to define them. Visual Studio is decent at leaving existing code alone. If you already have a property definition, it won't add it.
Again, if you have a ReadOnly property, there will be no set method.
I'm trying to obfuscate some VB.NET 2003 app.
The resulting assemblyes are obfuscated and "run" with some errors.
I cleaned all potential reflection problems, but I'm not being able to read the selected value of a combobox.
I load the Combobox using their Datasource properties, using a collection of "VTPair" (a class created by me with 2 properties: one of string type and other of object type to store the value)
This combobox handle pairs like "Male | M" or "Female | F".
When trying to see what is selected, I use if mycombo1.SelectedValue = "M" then
This code, after obfuscation, throws me an exception that cannot cast type "XX" to string "M".
So, I changed the code to something more correct, explicitly casting the selected value to String:
if ctype(mycombo1.SelectedValue,string) = "M" then
But the error is the same.
Debugin my original code, the SelectedValue property is of type "Object" but it is a string.
I tried using the ComboBox.SelectedItem property that is also an object but this time what is inside is of type "VTPair" (my own class) and then trying to access its "Value" property (which is of type Object) and trying to cast to string fails again.
Does anyone have an idea to "translate" this piece of code to work OK after Dotfucate it?
Thanks!
From MSDN:
ListControl.SelectedValue Property:
Gets or sets the value of the member property specified by the ValueMember property.
So whatever property NAME you set for the ValueMember property will be used when you use the SelectedValue property. So you may need to exclude from obfuscation, the property which you specify via the ComboBox.ValueMember property.
Not sure of the VB Syntax but in C# I think you would want something where the right-hand side is typeof(MyType). This way the type will be obfuscated to match the renamed type.