Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Passing objects ByRef to Properties

Status
Not open for further replies.

JonLittlechild

Programmer
Jul 27, 2003
4
GB
Hi, I'm new to VB.Net after years of VB5/6 development, so please forgive what might be a bit of a stupid question.

We're all familiar with the Property Set functionality in VB6 which works ByReference.

I've just found today that in VB.Net that you cannot pass an object to a property set (obviously using the .Net syntax) ByReference but that it MUST be passed ByValue. This seems like a bit of a backwards step to me.

So my question is, is there some way around this limitation or is there a generally accepted way of reproducing similar functionality to VB6's Propery Set without using properties?

Thanks in advance for your help.

Jon
 
I am not sure that I understand the question! It is possible to have objects as properties in .Net. When you pass an object as a parameter you are passing a pointer to the object, if you the value of the pointer points to the the same object you have passed your object.

Regards


 
Let explain with a bit of code, first the VB6 version:

Class - Class1.cls

Private mCmd As Command

Public Property Get Cmd() As Command
Set Cmd = mCmd
End Property
Public Property Set Cmd(pCmd As Command)
Set mCmd = pCmd
End Property

Module - Main.bas

Public Sub Main()
Dim MyClass1 As New Class1
Dim MyCommand As New ADODB.Command

MyCommand.CommandText = "some_stored_procedure"
Set MyClass1.Cmd = MyCommand
Debug.Print MyClass1.Cmd.CommandText

MyCommand.CommandText = "some_other_stored_procedure"
Debug.Print MyClass1.Cmd.CommandText
End Sub

In this instance, the two debugs will print out some_stored_procedure followed by some_other_stored_procedure.

Now if I recreate exactly the same situation in VB.Net as follows:

Class - Class1.vb

Private mCmd As SqlCommand

Public Property Cmd() As SqlCommand
Get
Return mCmd
End Get
Set (ByVal Value As SqlCommand)
mCmd = Value
End Set
End Property

Module - Main.bas

Public Sub Main()
Dim MyClass1 As New Class1
Dim MyCommand As New SqlCommand

MyCommand.CommandText = "some_stored_procedure"
MyClass1.Cmd = MyCommand
Debug.Print MyClass1.Cmd.CommandText

MyCommand.CommandText = "some_other_stored_procedure"
Debug.Print MyClass1.Cmd.CommandText
End Sub


In this instance the two debugs will print out some_stored_procedure followed by some_stored_procedure - i.e the same.

This is because when the line MyClass1.Cmd = MyCommand is executed a copy of the SqlCommand object is made rather than a pointer being passed. This means that the line MyCommand.CommandText = "some_other_stored_procedure" has no effect on the object held inside MyClass1. This seems flawed to me, it makes class properties pointless.

Jon
 
I tested both version of your code, they both gave the same result.

VB 6
some_stored_procedure
some_other_stored_procedure

VB.Net
some_stored_procedure
some_other_stored_procedure
The program '[2620] ConsoleApplication2.exe' has exited with code 0 (0x0)

The set command in VB6 is works exactly like the the assignment in vb.net. What you want is to for VB to create an object for you behind the scenes:

Code:
Sub Main()
        Dim MyClass1 As New Class1()
        Dim MyCommand As New SqlCommand()
        Dim a As String


        MyCommand.CommandText = "some_stored_procedure"
        MyClass1.Cmd = New SqlCommand()

        'Create new object and assign command text property
        MyClass1.Cmd.CommandText = MyCommand.CommandText
        Debug.WriteLine(MyClass1.Cmd.CommandText)

        'Object accessing same object
        MyCommand.CommandText = "some_other_stored_procedure"
        Debug.WriteLine(MyClass1.Cmd.CommandText)

    End Sub

which gives the results you are after. With most objects you can use the clone method to write the objects members to the new object, unfortunatly this is not available for the SqlCommand object, though if you create your own class that inherits from it you can use its protected MemberwiseClone method.

Regards
 
Ah... thanks for the reply, and I agree that the behaviour is the same. A lack of research on my part is to blame, sorry about that.

However, now I'm more confused. I originally tried this with a string variable rather than a SqlCommand and the behaviour is different. If you switch all instances of SqlCommand in the VB.Net version above to be String then you get the effect of passing the object (in this case a String) ByVal whereas when using the SqlCommand you get the effect of passing the object ByRef.

Therefore:
a) the behaviour is inconsistant - why do Strings behave differently from SqlCommands when in VB.Net the old native VB6 data types are meant to behave like objects?

b) when using the SqlCommand object you actually get the behaviour of passing ByRef even though the word ByVal is clearly visible in the code.

c) how is a developer meant to know when the code will behave ByRef and when will it behave ByVal?

Incidentally, the effect I originally wanted was to be able to pass object in ByRef, which it seems happens even when ByVal is explicitly declared. What do we do if we actually want to pass something in by value?

Jon
 
a. The same is also true of VB6, some types are value types and some type are reference types. You need to consult the documentation to see which type is which. Eg Strings and Arrays.

b. As explained before if you pass and object reference byval, you are passing the value of the address of the object, therefore you are passing the reference to the object.

c. By reading the documentation

As explained in my first post, you would need to use the objectsd clone method, in the rare case when the object does not provide a clone method you will have to write code to manually copy the properties.
 
Thanks John, I hadn't realised types behaved differently. To be honest, I've never come across an object that behaves ByVal in VB6. Obviously I know the base data types like string, long etc do, but then they're not objects! Still, I keep learning.

Now I know VB.Net behaves in this way, I know to look out for it.

Thanks,

Jon
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top