Using New Keyword but still just a reference? (VB.NET)

Arokh

Centurion
Joined
Apr 11, 2006
Messages
124
I thought I understood how this works, but I guess I was wrong:
Up until now I thought using the New Keyword was to create
a new Instance of for example a class, allocating space for its variables.
Without specifing New it only would declare it to something and
if one were to assign it to another instance of the class, only a referece would be passed.

For example:
Visual Basic:
Class ClassA
    Public VarA as String
    Public VarB as String
End Class

Dim SomeClass as New ClassA
SomeClass.VarA = "A"
SomeClass.VarB = "B"

Dim SomeOtherClass as New ClassA
SomeOtherClass = SomeClass

SomeOtherClass.VarA = "B"

Debug.Print(SomeClass.VarA)
Now I had assumed that Debug.Print would display "A" (see explanation above),
but it shows "B".
So SomeOtherClass is a reference to SomeClass?

How can I tell VB to make a copy of the class instead of just passing a reference?
SomeOtherClass = New SomeClass doesn't work.

What also interests me:
Is there a difference if I omit the New Keyword in the declaration of SomeOtherClass,
since I both cases only a reference is passed.




Although this is offtopic, I don't wanted to create another Thread for it:
The ArrayList Class for example
Dim AL as New ArrayList
AL(0) = "Bla"
Is the same as
AL.Item(0) = "Bla"

How can I create my own class which also accepts parameters
directly after the Class Instance Variable?
 
I've commented your code a bit in an attempt to explain...
Visual Basic:
Class ClassA
    Public VarA as String
    Public VarB as String
End Class
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'Creates a new instance of ClassA and assigns it to the SomeClass variable
Dim SomeClass as New ClassA    
SomeClass.VarA = "A"
SomeClass.VarB = "B"

'Creates a new instance of ClassA and assigns it to the SomeOtherClass variable
Dim SomeOtherClass as New ClassA    

'Assigns the SomeClass variable to the SomeOtherClass variable 
'- now both variables point to the original ClassA instance 
'and neither points to the second instance which is now eligible for garbage collection
SomeOtherClass = SomeClass   

'As both variables point to the original class instance this effectively set's VarA for both
SomeOtherClass.VarA = "B"

Debug.Print(SomeClass.VarA)

Then end result would be the same if you omitted the New keyword on the line
Visual Basic:
Dim SomeOtherClass as New ClassA
however the code with creates a new (but never used instance) while without you just declare a variable that can point to a valid instance.

For the last question they are called Default Properties un der VB.
 
Then how can I copy a class instance and store it into another variable of the same type?
Manually copying the variables from one to another is not really how I want to do it. he he

I guess one way would be the create a 'new' function which accepts its own class and
then there assign values to each variable inside the class:
Visual Basic:
Class ClassA
    Public VarA As String
    Public VarB As String

    Public Sub New(ByVal Item As ClassA)
        VarA = Item.VarA
        VarB = Item.VarB
    End Sub
End Class
Dim SomeOtherClass as New ClassA(SomeClass)
But I'm hoping there is an easier way which requires less code.
 
DotNet does not provide a mechanism to clone objects for you. You could write a function to automate it for you using reflection (assuming you have reflection permission), but even this can be problematic (which is why C++ has copy constructors). Shallow copies will often cause conflicts with shared resources and deep copies can not be automated.

Things can get hairy when you are creating memberwise clones of objects, because objects reference other objects, and the DotNet runtime has no way of knowing which referenced objects should also be duplicated and which ones should not (instead, they would only have their reference copied). For instance, if you wanted to copy an instance of your class, strings should probably not be duplicated. If you wanted to copy an instance of a Form object, controls would have to be duplicated (you can't use the same controls on two Forms at once). What's more, unmanaged resources would have to be allocated for the duplicated controls.

There is no reasonable way that DotNet could possibly sort this all out for you, which is why they don't provide a built-in function to copy objects. For something that seems so simple, copying objects is actually very complex and has to be done on a case-by-case basis, which means that you have to do it yourself. Your best bet is to create a C# style "copy constructor," i.e. your constructor that accepts an object and clones itself from that.
 
You can (should?) also look into the ICloneable interface, which forces you to implement a Clone() function to your class (the implementation is up to you)

Visual Basic:
Public Class MyClass Implements ICloneable
    Public StringA as String
    Public StringB as String
    Public OtherClass as MyOtherClass

    Public Function Clone() as MyClass Implements ICloneable.Clone
        Dim newClass as MyClass
        newClass.StringA = StringA
        newClass.StringB = StringB
        newClass.OtherClass = OtherClass.Clone()  ' this nested class needs to be cloned too
        return newClass
    End Function

End Class
 
Hmmm... the "copy" constructor was Microsoft's recommended technique. I'm not against use of the ICloneable interface, but unless you need to use this class in some abstract manner, neither approach has any merit over the other. I would say go with what's most intuitive.
 
ICloneable is absolutely necesary in certain situations

ICloneable is enforceable when dealing with interfaces as types. A copy constructor would not be useful in this context.

A good example is generics. If you require the ability to make copies of something in a generic class, you would have to make the copies through the ICloneable methods. The where clause only supports default constructors so it would be as if the copy constructor didn't exist within the generic class. By requiring Types that use the generic class to implement ICloneable, you guarantee that some kind of copy method will be provided.

Other examples might include the Factory pattern and object mocking.
 
Back
Top