Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2678
  • Last Modified:

VB.NET return by reference?

If I create a class and return a member of that class in a public function, does VB.NET do it by reference or value by default?
0
PLavelle
Asked:
PLavelle
  • 9
  • 5
  • 4
  • +7
2 Solutions
 
brother7Commented:
I believe if the class member returned is a reference type (for example, an object, string or array), it is returned by reference.  If it's a value type (for example, a numeric primitive or structure), it's returned by value.
0
 
Z_BeeblebroxCommented:
Hi,

A return value in all languages that I know of including .Net is by value and this is the only logical way it could be. This includes reference types. What this means is that using a function, you cannot change which object a member points to if it is a reference type, nor can you change its value if it is a value type. Of course, you can changes the data within the object that is pointed to if it is a reference type.

Zaphod.
0
 
GoodJunCommented:
Just as all the parameters passed in .net, by default it is byval
0
Veeam Disaster Recovery in Microsoft Azure

Veeam PN for Microsoft Azure is a FREE solution designed to simplify and automate the setup of a DR site in Microsoft Azure using lightweight software-defined networking. It reduces the complexity of VPN deployments and is designed for businesses of ALL sizes.

 
Bob LearnedCommented:
Are talking about that annoying problem that VB6 had where it wouldn't update a value passed in as a parameter?

If so, then Micro$oft has fixed that with VB.NET.  Try this:

   Class has one property:  Test As String

   Private Sub TestStuff()

      test.Test = "This is a test"

      ModifyString(test.Test)

      MsgBox(test.Test)

   End Sub

   Private Sub ModifyString(ByRef s As String)

      s = "Test"

   End Sub

After the call to ModifyString, the value in the message box will be 'Test'.  In VB6, it would still be the original value.
0
 
PLavelleAuthor Commented:
No just VB.NET, I think brother7 is right but I wanted to see something to prove it.
0
 
Bob LearnedCommented:
No, he is not completely correct.  

If you change all the strings in the above example to integers, and pass it to the ModifyString method, the value will be changed.  So, you see all ByRef parameters can be modified by a method if they are properties of a class.

It also applies if you use structures.
0
 
malharoneCommented:
the learnedone is correct ...

it's the custom property of the class
e.g.
public writeonly property password as string
 set (byval value as string)             '<--------- these are the ones that HAVE TO be byval. they can't be by ref.

  end set
end property

UNLESS you have
public password as string  '<--- in this case you lose the "writeonly" part of the property block

so you'd have to do this -- the traditional way


public function setPassword(byref password_ as string)  '<--- this would a reference
  password=password_
end function


and primitive types eventhough specified using byref, will always be passed as byval ... UNLESS you create a wrapper class ... e.g. if you want to pass an integer by ref... you'd have to do something like the following

public class MyInteger
  public value as Integer

  public sub new(optional byval value_ as Integer)
       value=value_
  end sub

end class

so .. asume i have a new object

public sub test()
   dim myInt as new MyInteger(100)
   msgbox(myInt.value)  '<---- 100
   changeInteger(myInt)
   msgbox(myInt.value)   '<---- 50

   dim x as integer=100
   msgbox(x) '<-- 100
   changeInteger(x)
   msgbox(x)  '<--- 100
end sub

public sub changeInteger(byref myInt as MyInteger)
   myInt.value=50
end sub

public sub changeInteger2(byref intVal as Integer)
    intVal=50
end sub
0
 
malharoneCommented:
oops ... i meant

public sub test()
   dim myInt as new MyInteger(100)
   msgbox(myInt.value)  '<---- 100
   changeInteger(myInt)
   msgbox(myInt.value)   '<---- 50

   dim x as integer=100
   msgbox(x) '<-- 100
   changeInteger2(x)         '<----------------------- this is changeInteger2 (NOT changeInteger)
   msgbox(x)  '<--- 100
end sub
0
 
kuzcoCommented:
As GoodJun said, all parameters are passed by value as default. So if objects are passed as parameters to methods, then a reference to the memory location in the heap will be created in the stack and since the reference of the object which is a value is only passed to the method, the object changes wont be reflected globally.

If you change the value of the reference itself, then it wont reflect globally unless ByRef is used.

Class has one property:  Test As String

   Private Sub TestStuff()

      test.Test = "This is a test"

      ModifyString(test.Test)

      MsgBox(test.Test)

   End Sub

   Private Sub ModifyString(ByRef s As String)

      s = "Test"

   End Sub

This will clear up all the basic doubts on how parameters both Value and Reference type work in .NET !

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfpassingmethodparameters.asp

Hope this helps.
0
 
brother7Commented:
The author's original question refers to the return value of a Function, not a Sub.
0
 
kuzcoCommented:
ahem return value of a function is exactly similar to how parameters to the function is passed. You could imagine a return value as a out param only that out params are passed ByRef by default which is the only difference from the return values which are passed as ByVal only.

Objects are reference types. So when you return an object from a function, the actual object's location in the heap is referenced and stored in a variable present in the stack. This value is what will be returned as the result of the function to the calling function. So you could say that all return values from functions are by default ByVal.
0
 
GoodJunCommented:
Kuzco, you did good.
0
 
mondayblueboyCommented:
PLavelle,

You meant, "Return by reference" or "Pass by reference" or “Return reference type”?

From what I know, C++ has the "Returning by Reference" features, and it's somewhat obscure because it allows using a function call on the left side of the equal sign.

Returning by reference sample:
==================================
[C++]

int x = 0;
int& ReturningByRef();  // function declaration

int main()
{
   ReturningByRef() = 100;  // function call on left side
   cout << "x=" << x << endl;
   return 0;
}

int& ReturningByRef()
{
   return x;
}

The output from the program, x = 100
==================================

This kind of feature is not supported by VB.NET and C#.
0
 
mondayblueboyCommented:
brother7,

I agree with you, I hope the following quick sample can help to describe better for "Returning Reference Type".

Module Module1

    Private x As String = "Initial Value"
    Private i As Integer

    Sub Main()
        x = ReturningString()
        If TypeOf x Is String Then
            Console.WriteLine("yes x is a string")
        End If
        i = ReturningInteger()
        'If TypeOf i Is Integer Then
        '    Console.WriteLine("yes i is an integer")
        'End If
    End Sub

    Private Function ReturningString() As String
        Return x
    End Function

    Private Function ReturningInteger() As String
        Return x
    End Function

End Module

If I remove the commented lines, I got compile error message: "error BC30021: 'TypeOf ... Is' requires its left operand to have a reference type, but this operand has the value type 'Integer'."

I think the message tells everything..
0
 
PLavelleAuthor Commented:
I am talking stictly about returning by reference in VB.NET. I know if C++ you can specify the return type as a pointer to an object, but does VB.NET always return a copy of the object or does it sometimes return some kind of pointer to the object if it is not a primitive type.
0
 
GoodJunCommented:
That message didn't tell it is byval or byref, it only tells that String is a reference type and the type of operator needs a reference type.
0
 
mondayblueboyCommented:
Well, if I change to,

Module Module1

    Private x As String = "Initial Value"
    Private o As Object

    Sub Main()
        x = ReturningString()
        If TypeOf x Is String Then
            Console.WriteLine("yes x is a string")
        End If

        o = ReturningInteger()
        If TypeOf o Is Integer Then
            Console.WriteLine("yes o is an integer")
        End If
    End Sub

    Private Function ReturningString() As String
        Return x
    End Function

    Private Function ReturningInteger() As Integer
        Return x
    End Function

End Module

It is compile successfully. Because the integer is being boxed to a reference-type of object. By knowing the difference between value-type and reference-type, it should be clear by know.

Please read this:
http://www.vbdotnetheaven.com/Code/Jun2003/2034.asp
0
 
GoodJunCommented:
Let's make sure that we all have the same definition of byref/byval for reference type.
1. no matter byval or byref, the reference type is in the heap and there is only one instance.
2. byref, the pointer itself is passed. No second location in stack is created.
3. byval, the pointer is copied and passed byval. a 2nd location in stack is created to point to the ONLY one object in the heap


When a function return a object, (byval or byref), we can all change the actual object in the heap. The question is how many point locations are created in the stack during the calling of the function. If only one, then by ref, if two, then by val.

I didn't see any official documentation says it byval or byref. (why?  it doesn't matter it is byval or byref anyway. the behavior is identical). I just Assuming that it follows the same way a parameters is passed bydefault.

function test() as class1
dim o as new class1
return o
end function

I assume, o is created and pointer is copied to the stack when it is returned. The 1st pointer is destroyed afer the return.
0
 
Zlatin ZlatevTechnical ArchitectCommented:
By default CLR assumes that all parameters are passed ByVal. When you pass parameter ByRef, actually you pass Referrence (pointer) ByVal.
If parameter is instance of a value type (e.g. System.Int32), a referrence to a COPY of this instance is passed.
If parameter is instance of a referrent type (e.g. System.String, System.Array, System.Object, System.Exception etc.), a referrence to the instance itself is passed.

Difference between byref and out parameters (out parameter is the value you return from function) is that out parameters are not needed to be initialized, but byref parameters MUST.
0
 
mondayblueboyCommented:
I think the question does not concern about behind the scene when calling a function, but rather what is the final result. Merely saying that by declare a function to return a reference-type means a number of bytes associated with the type are allocated on the heap. Accessing the return value means working with a reference to that object instead of directly with the bits (as with value-types).
0
 
GoodJunCommented:
No. The definition is as my previous comments. It is the definition by microsoft. You can see this from the link provided by kuzco, even though it talks about parameter not the function return.
0
 
brother7Commented:
OK, I think I have the definitive answer, as it relates to Function return values in VB.NET.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbtchmicrosoftvisualbasicnetinternals.asp

I quote from the section 'Storage Consumption - Copies of Variables':

"A variable is copied when it is assigned to another variable, when it is passed to a procedure ByVal, and when it is returned from a Function procedure. Visual Basic performs shallow copies, which means that it copies only the contents of a variable, and not any data to which those contents might refer. Therefore, a copy of a reference type variable duplicates only the four-byte pointer, and both the original and the copy point to the same data in memory. A copy of a value type variable replicates its entire contents in each new instance."

If I understand this correctly, it means that a Function's return value is always by value (for a value type, it's the actual value; for a reference type, it's the value of the four-byte pointer).
Hopefully, this is the clarity that the poster is looking for.
0
 
PLavelleAuthor Commented:
Thats exactly what I was looking for.
0
 
mondayblueboyCommented:
Good job brother7!
0
 
brother7Commented:
Aw, shucks... it was nuthin' (blush).
Is it time to divvy up the points?
0
 
kuzcoCommented:
hey wasn't that the same thing i mentioned in my last post ?! hmm ... Didn't dig up this article from MSDN though to prove the fact but i knew i was right !

If you'd ask me, any function should always return variables by value only, in .NET. Logically, for a reference type, the reference pointer is in the stack of the method accessing the object. Now, if it is not an out param, then the object pointer value in the local stack will be returned by value and then the stack corresponding to that method will be destroyed. The caller function shall copy the value of the pointer obtained from the other function and shall assign the value of the pointer to the variable in its function, thereby creating an effect of maintaining the same object reference. You should understand that, this is the primary reason that objects were designed to be placed in the heap in .NET so that only object references are created and destroyed in the stacks and so the source object remains the same maintaining consistency in object handling.

Ok ! Anyway if you've understood what i'm trying to say, then well and good :)
0
 
mondayblueboyCommented:
Hey, wait a minute. I didn't read the article until I realized the quote is not in the link given by brother7 - Visual Basic .NET Internals? Isn't that should be:

Using Classes and Structures in Visual Basic .NET
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbtchuseclassstruct.asp

Let me re-quote,

>> A variable is copied when it is assigned to another variable,
>> when it is passed to a procedure ByVal, and when it is returned
>> from a Function procedure.
That's fine, but it didn't mention about "return from a function procedure ByVal", only "when passed to a procedure ByVal".

>> Visual Basic performs shallow copies, which means that it copies
>> only the contents of a variable, and not any data to which those
>> contents might refer.

And read this part carefully,
>> Therefore, a copy of a reference type variable duplicates only the four-byte
>> pointer, and both "the original and the copy point" to the same data in memory.
Is this the definition of returning from a function procedure ByVal??

And this,
>> A copy of a value type variable replicates its entire contents in each new instance.

Anyone..
0
 
mondayblueboyCommented:
0
 
mondayblueboyCommented:
And brother7, thanks for the direction. You da man!
0
 
mondayblueboyCommented:
And don't forget the original question, PLavelle has rectified it to:

>> but does VB.NET always return a copy of the object or
>> does it sometimes return some kind of pointer to the
>> object if it is not a primitive type.
0
 
PLavelleAuthor Commented:
Ok, a great discussion by everyone but after reviewing I think I have to give the answer to brother7 and some points to kuzco for clarifying how it works.
0
 
scotthagieCommented:
Interesting thread. It's a serious oversite that you can't return a vlue byref in VB.Net, but can in C#. One of the few times I have regretted my choice of languages in .Net. I guess I will have to pass an input parameter as byref, and change that, but that is very inelegant.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 9
  • 5
  • 4
  • +7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now