Class Variable Assignments ... need help

kimosavi

Active member
Joined
Apr 9, 2009
Messages
34
Location
Chicago, IL
Programming Experience
3-5
Hi,

I am trying to work with classes and variables and don't seem to understand some behavior that is going on.

first off the class

VB.NET:
Public Class csSession
  Public ID As Integer
  Public Name As String
End Class

Usage and behavior (example code)

VB.NET:
Dim S1 as new csSession
Dim S2 as new csSession

S1.ID = 1
S1.Name = "1st Session"

S2 = S1

S2.ID = 99

When I assign S2 = S1 all the values of S1 passes to S2 but also there is a "link" or bond between the two variables now.

if I change the values of S2 this automatically changes the values of S1!!

Why does this happen and how can I prevent it?

I just want to pass the variables values contained S1 to S2.

Thanks in advance!
 
When I assign S2 = S1 all the values of S1 passes to S2

No they don't.

Classes are reference types, which means that a variable of that type contains a reference to an object rather than an object itself. That means that this line:
VB.NET:
S2 = S1
is not copy data from one object to another, but rather assigning an object to a variable. After that line, S1 and S2 refer to a single object and the other object you created has been discarded. If you want to copy data from one class instance to another then that's what you actually have to do, property by property.

Note that, if you were using a structure instead of a class, what you expect to happen would actually happen. That's because structures are value types, i.e. a variable of that type contains the object itself.
 
Thanks jmcilhinney for your reply.

I was just now playing around with structures and think for my purpose is the way to go. But this caused another issue.

my initial class was missing something
VB.NET:
Public Class csSession
  Public ID As Integer
  Public Name As String
  Public Member as new List(of csMembers)
End Class

Public Class csMembers
  Public ID as integer
  Public Name as string 
End Class

this is how I have been using the class.

now with the structure this presents a problem for my List(Of xxx)

VB.NET:
Public Structure ssSession
  Public ID As Integer
  Public Name As String
  Public Member as new List(of ssMembers) <-- Not permitted unless shared (don't want it shared)
End Class

Public Structure ssMembers
  Public ID as integer
  Public Name as string 
End Structure

I need to have a structure that will have a variable within that can be dimensioned and easy access

like

VB.NET:
 Session.member(0).ID

I can it define it like this

VB.NET:
Public Structure ssSession
  Public ID As Integer
  Public Name As String
  Public Member() as ssMembers 
End Class

but don't know how to add or manipulate the Member variable this way. How do I increase the dimension? redim preserve? how do I search or look for a value?

all this nice things where done for me by the List(Of xxx).

Can you give me few pointer on how to achive my goal?

Thanks!
 
Hi,

Solve my problem to have everything I wanted from my class but with the advantages of passing just the values and using my List(Of xxx)

VB.NET:
Public Structure ssSession
  Public ID As Integer
  Public Name As String
  Public Member as List(of ssMembers) 
  Public Sub New(ByVal e as Integer) <-- necessary to set a parameter otherwise will not work
       Member = New List(Of ssMembers)
  End Sub
End Class

Public Structure ssMembers
  Public ID as integer
  Public Name as string 
End Structure

Usage

VB.NET:
Dim S1 as new ssSession(0) <-- needs a parameter even if it is not used
Dim S2 as new ssSession(0)

' Add some values to S1

S2 = S1

Now if I modify S2 I will not affect S1, plus I get to use S1.Members(x)

Is it better then to SHARED the New() Sub? what is the difference then?
 
My problem persists. It won't leave me alone.

now all the values in ssSession are save from being altered if assigned to another variable.

but

VB.NET:
Public Member as List(of Members)

is still being associated somehow. Although part of a structure.

If I do

VB.NET:
S2.Member.Clear()

all the members on S1 are also clear.

how can I prevent this from happening? any thought?!
 
It's exactly the same thing. List(Of T) is a class so, when you copy the structure, you are only copying a reference to the List, so there's still only one object. Also, adding a fake parameter to a structure constructor is a filthy hack that won't even work if you don't use the constructor.

What you should be doing here defining a class, implementing the ICloneable interface and implementing the Clone method such that it creates as deep a copy as you need.
 
Friend Class Member

    Private _id As Integer
    Private _name As String

    Public Property ID() As Integer
        Get
            Return _id
        End Get
        Set(ByVal value As Integer)
            _id = value
        End Set
    End Property

    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property

End Class


Friend Class Session
    Implements ICloneable
    
    Private _id As Integer
    Private _name As String
    Private _members As New List(Of Member)

    Public Property ID() As Integer
        Get
            Return _id
        End Get
        Set(ByVal value As Integer)
            _id = value
        End Set
    End Property

    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property

    Public ReadOnly Property Members() As List(Of Member)
        Get
            Return _members
        End Get
    End Property

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim copy As New Session

        With copy
            ._id = Me._id
            ._name = Me._name
            ._members.AddRange(Me._members)
        End With

        Return copy
    End Function

End Class
Note the more correct use of public properties and private fields rather than public fields. Also note the ICloneable implementation, which creates a copy with the same data. Note that the copy contains its own List(Of Member) object, but that List still contains the same Member objects as the other List. Editing the List won;t affect the other one but editing the items in the List will. This is how classes work.
 
thanks jmcilhinney!

if the past I had implemented something similar to what you are explaining, but had to assign variable by variable:

VB.NET:
  Public Sub ValueOf(ByVal sSession As csSession)
        ID = sSession.ID
        Name = sSession.Name

        '****** Add Members Values to New Variable
        Members.Clear()
        For Each sMember As csMembers In sSession.Members
            Members.Add(sMember)
        Next
        '******
    End Sub

Sub Main()
 
 Dim Session1 As New csSession
 Dim Session2 As New csSession

Session2.ValueOf(Session1)

End Sub

This is very similar to the cloning, but done manually and have to keep track of the objects within the class and add them in the ValueOf Function.

I really liked your approach since I don't have to deal with the basic type assignment, just worry about the lists and other classes if necessary.

The codes looks great, here is my implementation:

VB.NET:
Public Class csSession
    Implements ICloneable
    Public ID As Integer
    Public Name As String
    Public Members As New List(Of csMembers)

    Public Function Clone() As Object Implements ICloneable.Clone
        'Clone the Session
        Dim sSession As csSession = DirectCast(MemberwiseClone(), csSession)

        'Add Cloned Member
        sSession.Members = New List(Of csMembers)
        sSession.Members.AddRange(Members)

        Return sSession
    End Function
End Class

I do want to ask you a question. Is the Implements ICloneable really needed?

I saw another site where they implement the same approach without the ICloneable:

Object.MemberwiseClone Method (System)

VB.NET:
Public Class Person 
    Public Age As Integer
    Public Name As String
    Public IdInfo As IdInfo

    Public Function ShallowCopy() As Person
       Return DirectCast(Me.MemberwiseClone(), Person)
    End Function

    Public Function DeepCopy() As Person
       Dim other As Person = DirectCast(Me.MemberwiseClone(), Person) 
       other.IdInfo = New IdInfo(Me.IdInfo.IdNumber)
       Return other
    End Function
End Class

so is the ICloneable needed?

Thanks for all your help.
 
Implementing an interface means adhering to a standard contract, which means the implementation should fulfill the interface purpose. Implementation is known by documentation and can also be discovered. Implementing IClonable means your object intends to provide a deeper cloning than the default Object.MemberwiseClone method. Other code may in some context do some cloning and use the type system to determine how to clone any given object. MemberwiseClone will always be the default option, but the code can discover that an object implements IClonable and use that in preference if it exists. Code performing automated type discovery would otherwise have no way of knowing if any arbitrary method provided a cloning functionality. If you write a method that provides cloning beyond MemberwiseClone there is no reason not to flag it IClonable, that just adds to the value of the code, even if you don't see any added value to that right now. Other developers reading the code will immediately recognize IClonable, but a cloning method that is not IClonable will raise questions (apart from a public MemberwiseClone overload).
 
Thanks Johnh!

Your comments were really useful. Although I have been programming for a long time, I have come on and off coding for some time, in most cases not paying a lot of attention to new ways of doing things unless needed.

In terms of running the code, I guess it makes not much difference, but it will if you are programming on a big project or handing code to another programmer to understand the process. It makes now more sense.

You also mentioned that :
Implementation is known by documentation and can also be discovered

When you refer documentation, you mean a tool or program that will write documentation around my code. Like Documentation!X right?

I tried understanding also what you said :
Implementing IClonable means your object intends to provide a deeper cloning than the default Object.MemberwiseClone method

can you explain the
provide a deeper cloning
part?

Thanks for all this! very insightful!
 
I also have a question regarding memory management and these variables.

I will explain my question.

When I create Session1 from csSession and assign information to it, space is allocated in memory to hold the information of the variable Session1 (Stack and Heap right?)

If I create Session2 and do a reference assignment (Session2 = Session1) Session2 will point to the memory space where Session1 was create and is holding the information.

the memory is the ONLY clear when I get right of Session1 (Session1 = nothing, or Session1.dispose, this is just the Heap right?).

if I use cloning (Session2 = Session1.Clone) now two memory variable will hold space hence more memory will be used in the system.

I want to make sure I am cleaning up after myself.

so do I need to dispose of the variables? I am just dimensioning them in a sub routine, once the rutine is done the variable should disappear from memory right?
 
By "documentation" JohnH means the MSDN Library and also the hints provided by Intellisense. That information is derived in large part from the XML comments that the developer uses to annotate their types and members. There are various tools that can turn those comments, which VS outputs to an XML file, into documentation, including the now defunct NDoc and Microsoft's Sandcastle.

A shallow copy is one that copies field values only. That means that, for reference type fields, only the reference is copied. That means that field of both the original and the copy refer to the same object. For instance, if there is a List, the shallow copy will contain a reference to the same List object, so adding an item via the copy will affect the original. A deep copy is where reference type objects are duplicated too. How deep a deep copy goes is up to the developer, so it always requires custom code.
 
Cloning means you create duplicate objects, so that means duplicate memory usage also. This to the degree of how deep the clone is. Copying a reference object means only the reference is duplicated, not the object. Value types is always copied by value, so for these memory is also always duplicated with a cloned object.

Automatic memory management in the .Net platform means value objects are freed when variables go out of scope, and reference objects freed when there are no references to them. Setting a reference type variable to Nothing is only needed to free an object if the variable has a longer lifetime/scope than the object needs. IDisposable interface (that provides the Dispose method) is an interface used to implement custom cleanup of objects, primarily for unmanaged resources.
 
Back
Top