VB.Net - Using a subclass in a class - vb.net

Trying to convert some VBA code to VB.Net and getting hung up on some class issues. I have a main class: clsComputer. It has a subclass: clsHardDrive. Since a computer can have more than 1 hard drive, it's Get and Set properties look like this in clsComputer:
Private pHardDrive(8) As clsHardDrive
Public Property Get HardDrive(index As Integer) As clsHardDrive
If pHardDrive(index) Is Nothing Then Set pHardDrive(index) = New clsHardDrive
Set HardDrive = pHardDrive(index)
End Property
Public Property Set HardDrive(index As Integer, value As clsHardDrive)
pHardDrive(index) = value
End Property
This allows me to do something like this in code:
objComp.HardDrive(0).Size = "500"
objComp.HardDrive(1).Size = "1000"
However, I don't know how to convert this to VB.Net. I tried this:
Property HardDrive As HDD
Get (ByVal index As Integer)
Return pHardDrive(index)
End Get
Set (ByVal index As Integer, value As HDD)
pHardDrive(index) = value
End Set
End Property
But it gives a compile error: Property without a 'ReadOnly' or 'WriteOnly' specifier must provide both a 'Get' and a 'Set'. (BC30124)
Searching that error isn't very helpful: To correct this error make sure you include both a Get procedure and a Set procedure between the Property statement and the End Property statement. I have both Get and Set, and I think they are properly terminated. I've also searched for examples on using one class within another, but I didn't find anything useful.
How do I get the same functionality in VB.Net that I have in VBA? EG, how do I create the instances of HardDrive so that one computer object can have many hard drive objects?

Indexed properties still exist in VB.NET, just like classic COM-based VB.
You just have the syntax wrong. Indexed properties really just a special case of a parameterized property, so the index is taken as a parameter for the entire property, not the individual Get and Set statements.
Public Class Computer
Private m_hardDrives(8) As HDD
Public Property HardDrive(ByVal index As Integer) As HDD
Get
Return m_hardDrives(index)
End Get
Set(ByVal value As HDD)
m_hardDrives(index) = value
End Set
End Property
End Class

Related

Modifiy the default auto implement "template" in VB.net 2015

in a class i declare a variable private :
Private test As String
then i right click do quick action and generate :
Public Property Test1 As String
Get
Return test
End Get
Set(value As String)
test = value
End Set
End Property
Do you know a way to modify the autogenerate code produce?
I want to add something like :
Public Property Test1 As String
Get
Return test
End Get
Set(value As String)
Tmp_Val = test
test = value
RaiseEvent VariableChanged(test, Tmp_Val, VarDesc("test"))
End Set
End Property
if somebody know a place where the "template" is stored?
Thanks.
quick actions are used for refactoring and pointers toward fixing errors in your code, not so much for automatic code generation. Unfortunately, I haven't found any way to edit these. You can however edit code snippets, but this is laborious to say the least. There is an extension you can install which is supposed to make snippet editing easier - I haven't tried it, but it comes via Microsoft#s Visial Studio Gallery -
Snippetizer

Initialize a value for a shared property

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.

Why can't define get type and set type distinctly within Properties?

Here is the problem, I wanted to define a property which accepts decimal numbers and do some process on the value and return string such as the below:
Public Property Amount() As String
Get
Return Utility.PaddingRight(Me.msAmount.ToString(), 10)
End Get
Set(ByVal vsValue As Decimal)
Me.msAmount = vsValue
End Set
End Property
But compilers warns "Set parameters must have the same type of the containing property."
It doesn't look like it should throws an error since it looks legit.
The reason that you can't is because what you put into a property should be exactly the same as what you get out of it. If the type changed then this condition would never be true. Microsoft's spec says that "Properties are like smart fields". Imagine if a field (class variable) changed between reading and writing.
Your goal is completely valid but that's not the intended use for properties. (By "intended goal" I mean Microsoft's intended goal.) Your design would also opens doors for potential problems if an invalid or null string were passed in. One of the design goals for properties is that they are light weight and shouldn't throw errors. They can but shouldn't. The recommended solution is to use the TryParse pattern for your property.
EDIT
Sorry, my brain was sidetracked, your goal is changing the getter, not the setter. The pattern that you're looking for is just a read-only property (as #msarchet pointed out) that's specific to your getter. For instance, AmountForPrint or something. You should still include a read/write for your actual value, too.
Public ReadOnly Property AmountForPrint
Get
Return Me.Amount.ToString()
End Get
End Property
Public Property Amount As Integer
Get
End Get
Set(value As Integer)
End Set
End Property
I think you need a to do this with a method not a property
Public Function Amount(ByVal value As Decimal) As String
End Function
This is just a shot in the dark . . .
Set(ByVal vsValue As String)
Me.msAmount = System.Convert.ToDecimal(vsValue)
End Set
You'd be far better off doing this as such
Public Read Only Property Amount() As String
Get
Return Utility.PaddingRight(Me.msAmount.ToString(), 10)
End Get
End Property
Public Sub SetAmount(ByVal value As Decimal)
Me.msAmount = value
End Sub

Is it correct to correct properties values on the fly?

Is it correct to correct properties values on the fly?
for example: (note the .ToLower)
Public Property X() As String
Get
Return _x.ToLower
End Get
Set(ByVal Value As String)
_x = value.ToLower
End Set
End Property
There is nothing incorrect about standardizing your properties in getter/setters. Without any context of what X represents it is hard determine if a property is the right way to access and update the value of X. Depending on the application, it might make sense to not have a public setter at all but instead have a method such as CustomerRequestedXToChange(XUpdatedValue as String)
Some improvements to your code though:
Be sure that _x is private so that no other classes can modify the value.
Only perform ToLower on the setter, not both. As long as you follow the next convention that should work fine.
All calls to _x within this class should go through X, that way the value of _x will be correct.

VB.net 2008 Property Array

Hi can anyone help here? I am currently learning VB.net but for a project I need to create and array and pass it using a property. The data to be passed will be a train's destination, the time its due and the expected time of the train. I was wondering if someone could simplly explain how to first produce an array and then show how to pass it to a custom control using a property any help would be great.
Thank you.
If you want to provide multiple values to a control, one clean way to do this is to have separate properties, one for each value, instead of trying to pass them all in one array. Another clean way to do this is to create a new class (type) that combines all these values into one structure, and expose a single property of that type. For example:
Public Class TrainDetails
Private _destination As String
Private _due As DateTime
Private _expected as DateTime
Public Property Destination As String
Get
Return _destination
End Get
Set
_destination = Value
End Set
End Property
Public Property Due As DateTime
Get
Return _due
End Get
Set
_due = Value
End Set
End Property
Public Property Expected As DateTime
Get
Return _expected
End Get
Set
_expected = Value
End Set
End Property
End Class
(Note, I think it's necessary to implement property procedures instead of directly exposing the internal field values in order for the properties to show up in a property grid.)
So if you have this class, then you can create a property of type TrainDetails on your control that will encapsulate all these properties in one value. I think they will be editable in the property grid as a single property with an expandable "+" next to it to edit the individual values.