|
-
Oct 3rd, 2010, 02:08 PM
#1
Thread Starter
Lively Member
[Resolved] Class within a class
I have two classes:
Code:
Public Class Sensor
Public Number As Integer
Public Name As String
Public Value As Integer
End Class
Public Class Transmitter
Public Number As Integer
Public Name As String
Public Type As Integer
Public MySensor() As Sensor
End Class
but I can't work out how to populate the sub class:
Code:
Dim MyTX As Transmitter
Dim MySens As Sensor
Dim MyTransmitter(9) As Transmitter
MyTX = New Transmitter
MySens = New Sensor
MyTX.Name = "Transmitter"
MySens.Name = "Sensor"
MyTransmitter(0) = MyTX
MyTransmitter(0).MySensor(0) = MySens
Debug.Print(MyTransmitter(0).MySensor(0).Name)
as I get an object not set error. Can someone give me the correct syntax?
Last edited by consciouspnm; Oct 7th, 2010 at 05:14 AM.
-
Oct 3rd, 2010, 03:03 PM
#2
Frenzied Member
Re: Class within a class
Try using the "new" keyword. You are telling the variable what object it can contain, but not actually making it contain said object.
-
Oct 3rd, 2010, 03:53 PM
#3
Re: Class within a class
Hey,
If I were you, I would be more inclined to be using Generic Lists of objects, rather than arrays.
Have a look at the following, which does what you were trying to do:
Code:
Public Class Sensor
Public Number As Integer
Public Name As String
Public Value As Integer
End Class
Public Class Transmitter
Public Number As Integer
Public Name As String
Public Type As Integer
Public MySensors As New List(Of Sensor)
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim MyTX As Transmitter
Dim MySens As Sensor
Dim MyTransmitters As New List(Of Transmitter)
MyTX = New Transmitter
MySens = New Sensor
MyTX.Name = "Transmitter"
MySens.Name = "Sensor"
MyTX.MySensors.Add(MySens)
MyTransmitters.Add(MyTX)
Debug.Print(MyTransmitters(0).MySensors(0).Name)
End Sub
Hope that helps!!
Gary
-
Oct 3rd, 2010, 11:24 PM
#4
Re: Class within a class
To extend on Gary's suggestion, if you look at basically every collection exposed via a property in the .NET Framework, the property is ReadOnly. The reason is that consumers can then add and remove items, but the cannot assign a whole new collection. The most appropriate implementation is thus:
vb.net Code:
Public Class Sensor '... End Class Public Class Transmitter Private _sensors As New List(Of Sensor) '... Public ReadOnly Property Sensors() As List(Of Sensor) Get Return Me._sensors End Get End Property '... End Class
You can extend that further to provide lazy loading if appropriate, which means that the List is not created until it's used for the first time:
vb.net Code:
Public Class Sensor '... End Class Public Class Transmitter Private _sensors As List(Of Sensor) '... Public ReadOnly Property Sensors() As List(Of Sensor) Get If Me._sensors Is Nothing Then Me._sensors = New List(Of Sensor) End If Return Me._sensors End Get End Property '... End Class
Finally, I notice that your classes are declared Public, meaning that they can be accessed from outside the project. Is that what you really want? If not then they should be declared Friend. Everything should always have the narrowest scope possible. If you really do want the classes exposed publicly then the .NET convention is to not expose properties of type List(of T), but rather define your own custom collection:
vb.net Code:
Public Class Sensor '... End Class Public Class SensorCollection Inherits System.Collections.ObjectModel.Collection(Of Sensor) End Class Public Class Transmitter Private _sensors As SensorCollection '... Public ReadOnly Property Sensors() As SensorCollection Get If Me._sensors Is Nothing Then Me._sensors = New SensorCollection End If Return Me._sensors End Get End Property '... End Class
As you can see, the SensorCollection class requires basically no code because everything is inherited. You do have the freedom to override certain Protected members to implement custom behaviour though.
-
Oct 4th, 2010, 12:57 AM
#5
Re: Class within a class
Ah, good point about the ReadOnly property.
Gary
-
Oct 4th, 2010, 08:05 AM
#6
Frenzied Member
Re: Class within a class
I never really understood why it's good practice to create custom collections instead of using List(Of T) when exposing collections... Does anyone know the answer?
Please rate helpful ppl's posts. It's the best 'thank you' you can give 
-
Oct 4th, 2010, 08:38 AM
#7
-
Oct 4th, 2010, 08:59 AM
#8
Frenzied Member
Re: Class within a class
So basically the issue is that if a list makes its way into a library, then it won't be as easy to provide custom behaviour for the list if such behaviour is required?
Please rate helpful ppl's posts. It's the best 'thank you' you can give 
-
Oct 4th, 2010, 09:03 AM
#9
Re: Class within a class
That is the way that I read it, yes.
Let's say you are creating a class, and you know that other people are going to be inheriting from that class, then you want to make it as "easy" as possible for them to alter the behaviour as and when required. Following this guideline makes it possible.
This is one of the many rules that is enforced using Code Analysis (formally FXCOP). You might want to think about turning it on in your application. Helps you remember most of the best practices for your application.
Gary
-
Oct 4th, 2010, 09:29 AM
#10
Frenzied Member
Re: Class within a class
Thanks for clearing it up for me
Please rate helpful ppl's posts. It's the best 'thank you' you can give 
-
Oct 4th, 2010, 12:03 PM
#11
Thread Starter
Lively Member
Re: Class within a class
Thanks, I've got Gary's solution working. I'm not quite sure I understand having to change it to read only though. I'll have to read the msdn link.
-
Oct 4th, 2010, 12:20 PM
#12
Frenzied Member
Re: Class within a class
 Originally Posted by consciouspnm
Thanks, I've got Gary's solution working. I'm not quite sure I understand having to change it to read only though. I'll have to read the msdn link.
Basically, if the collection is read only, it will not allow an operation such as this one:
Code:
Public ReadOnly Property Sensors() As List(Of Sensor)
Get
Return Me._sensors
End Get
End Property
Sub ChangeProperty()
Dim sen As New List(Of Sensor)
Sensors.Add(New Sensor) 'This line will work properly
Sensors=sen 'This line will display an error since Sensors is ReadOnly
End Sub
As you can see, you can modify the collection itself, but not replace it with a completely new collection.
Last edited by obi1kenobi; Oct 4th, 2010 at 12:21 PM.
Reason: added info
Please rate helpful ppl's posts. It's the best 'thank you' you can give 
-
Oct 4th, 2010, 03:44 PM
#13
Re: Class within a class
 Originally Posted by consciouspnm
Thanks, I've got Gary's solution working. I'm not quite sure I understand having to change it to read only though. I'll have to read the msdn link.
Think of it like a bank that holds your money. You can always add more money, or remove some money from it. You can even remove all the money from the bank, and put some different money in. But you can never replace the entire bank with a different bank! In this sense, the bank is a ReadOnly collection of your money. ReadOnly does not mean you cannot do anything with it (as you can still add/remove money), it merely means you cannot replace it with something else (assign a different object to it).
-
Oct 5th, 2010, 01:01 AM
#14
Re: Class within a class
 Originally Posted by NickThissen
Think of it like a bank that holds your money. You can always add more money, or remove some money from it. You can even remove all the money from the bank, and put some different money in. But you can never replace the entire bank with a different bank! In this sense, the bank is a ReadOnly collection of your money. ReadOnly does not mean you cannot do anything with it (as you can still add/remove money), it merely means you cannot replace it with something else (assign a different object to it).
That's a nice analogy, I like it!!
Gary
-
Oct 5th, 2010, 01:02 AM
#15
Re: Class within a class
 Originally Posted by consciouspnm
Thanks, I've got Gary's solution working. I'm not quite sure I understand having to change it to read only though. I'll have to read the msdn link.
Have you been able to get something working yet?
Gary
-
Oct 5th, 2010, 01:13 AM
#16
Re: Class within a class
You want to be able to add sensors to the list, right? You want to be able to do this:
vb.net Code:
myTransmitter.Sensors.Add(someSensor) myTransmitter.Sensors.Remove(someOtherSensor)
That is equivalent to this:
vb.net Code:
Dim sensors As List(Of Sensor) = myTransmitter.Sensors senors.Add(someSensor) sensors.Remove(someOtherSensor)
Notice that, in order to add and remove items in the collection, you only ever need to GET the value of the Sensors property. You never need to SET it. As such, the Sensors property should only have a getter, not a setter. That is the definition of a ReadOnly property.
-
Oct 5th, 2010, 12:26 PM
#17
Thread Starter
Lively Member
Re: Class within a class
Using that method, how do I update the values of the sensors?
At the moment I can say:
Code:
MyTransmitters(0).Sensors(0).Value = 53
All the transmitter and sensor config is in an XML file which is read in at the start so the .Add is fine but I need to update the Value property when required.
-
Oct 5th, 2010, 12:43 PM
#18
Re: Class within a class
Well after you change the values you'll have to save them back to the XML file. I'd create a Save method, called after making all the changes, instead of saving the file every single time a change is made.
-
Oct 5th, 2010, 12:44 PM
#19
Frenzied Member
Re: Class within a class
You can keep the code as it is now; it will work properly even if the collection is read-only. Basically, anything short of creating a new collection and assigning it to Sensors will work exactly the same. Try it in VS and you'll see
Please rate helpful ppl's posts. It's the best 'thank you' you can give 
-
Oct 5th, 2010, 01:26 PM
#20
Thread Starter
Lively Member
Re: Class within a class
 Originally Posted by NickThissen
Well after you change the values you'll have to save them back to the XML file. I'd create a Save method, called after making all the changes, instead of saving the file every single time a change is made.
I meant I wanted to update the Values in the collection, not the XML file! The values are written off the SQL from the sensor collection.
-
Oct 5th, 2010, 05:38 PM
#21
Re: Class within a class
As has already been said, the code you already have is fine. It's the Sensors property that is read only. Look at your own code:
Code:
MyTransmitters(0).Sensors(0).Value = 53
Are you setting the Sensors property there? No, you aren't. You are only getting it. You get the Sensors property, get an item form the collection and then set the Value property. The Value property of a Sensor is not ReadOnly, so there's nothing to stop you setting it. It is only the Sensors property that is ReadOnly, because you never need to assign a whole new collection to it.
-
Oct 6th, 2010, 02:37 AM
#22
Re: Class within a class
consciouspnm, did you try the above?
If so, and it worked, can you remember to come back and mark your thread as resolved?
Thanks
Gary
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|