Results 1 to 22 of 22

Thread: [Resolved] Class within a class

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Feb 2005
    Location
    Huddersfield, England
    Posts
    83

    Resolved [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.

  2. #2
    Frenzied Member
    Join Date
    Sep 2006
    Location
    Scotland
    Posts
    1,054

    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.

  3. #3
    PowerPoster gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    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

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    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:
    1. Public Class Sensor
    2.     '...
    3. End Class
    4.  
    5. Public Class Transmitter
    6.  
    7.     Private _sensors As New List(Of Sensor)
    8.  
    9.     '...
    10.  
    11.     Public ReadOnly Property Sensors() As List(Of Sensor)
    12.         Get
    13.             Return Me._sensors
    14.         End Get
    15.     End Property
    16.  
    17.     '...
    18.  
    19. 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:
    1. Public Class Sensor
    2.     '...
    3. End Class
    4.  
    5. Public Class Transmitter
    6.  
    7.     Private _sensors As List(Of Sensor)
    8.  
    9.     '...
    10.  
    11.     Public ReadOnly Property Sensors() As List(Of Sensor)
    12.         Get
    13.             If Me._sensors Is Nothing Then
    14.                 Me._sensors = New List(Of Sensor)
    15.             End If
    16.  
    17.             Return Me._sensors
    18.         End Get
    19.     End Property
    20.  
    21.     '...
    22.  
    23. 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:
    1. Public Class Sensor
    2.     '...
    3. End Class
    4.  
    5. Public Class SensorCollection
    6.     Inherits System.Collections.ObjectModel.Collection(Of Sensor)
    7. End Class
    8.  
    9. Public Class Transmitter
    10.  
    11.     Private _sensors As SensorCollection
    12.  
    13.     '...
    14.  
    15.     Public ReadOnly Property Sensors() As SensorCollection
    16.         Get
    17.             If Me._sensors Is Nothing Then
    18.                 Me._sensors = New SensorCollection
    19.             End If
    20.  
    21.             Return Me._sensors
    22.         End Get
    23.     End Property
    24.  
    25.     '...
    26.  
    27. 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.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5
    PowerPoster gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    Re: Class within a class

    Ah, good point about the ReadOnly property.

    Gary

  6. #6
    Frenzied Member obi1kenobi's Avatar
    Join Date
    Aug 2007
    Posts
    1,091

    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

  7. #7

  8. #8
    Frenzied Member obi1kenobi's Avatar
    Join Date
    Aug 2007
    Posts
    1,091

    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

  9. #9
    PowerPoster gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    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

  10. #10
    Frenzied Member obi1kenobi's Avatar
    Join Date
    Aug 2007
    Posts
    1,091

    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

  11. #11

    Thread Starter
    Lively Member
    Join Date
    Feb 2005
    Location
    Huddersfield, England
    Posts
    83

    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.

  12. #12
    Frenzied Member obi1kenobi's Avatar
    Join Date
    Aug 2007
    Posts
    1,091

    Re: Class within a class

    Quote Originally Posted by consciouspnm View Post
    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

  13. #13
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Class within a class

    Quote Originally Posted by consciouspnm View Post
    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).

  14. #14
    PowerPoster gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    Re: Class within a class

    Quote Originally Posted by NickThissen View Post
    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

  15. #15
    PowerPoster gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    Re: Class within a class

    Quote Originally Posted by consciouspnm View Post
    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

  16. #16
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    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:
    1. myTransmitter.Sensors.Add(someSensor)
    2. myTransmitter.Sensors.Remove(someOtherSensor)
    That is equivalent to this:
    vb.net Code:
    1. Dim sensors As List(Of Sensor) = myTransmitter.Sensors
    2.  
    3. senors.Add(someSensor)
    4. 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.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  17. #17

    Thread Starter
    Lively Member
    Join Date
    Feb 2005
    Location
    Huddersfield, England
    Posts
    83

    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.

  18. #18

  19. #19
    Frenzied Member obi1kenobi's Avatar
    Join Date
    Aug 2007
    Posts
    1,091

    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

  20. #20

    Thread Starter
    Lively Member
    Join Date
    Feb 2005
    Location
    Huddersfield, England
    Posts
    83

    Re: Class within a class

    Quote Originally Posted by NickThissen View Post
    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.

  21. #21
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    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.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  22. #22
    PowerPoster gep13's Avatar
    Join Date
    Nov 2004
    Location
    The Granite City
    Posts
    21,963

    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
  •  



Click Here to Expand Forum to Full Width