473,395 Members | 2,436 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Please help me clarify these byVal vs. byRef subtleties

Hi,

Please let me know if I am interpreting this correctly. I've done a
little testing of the difference between passing parameters byVal and
byRef, and the results were slightly non-intuitive, as I expected. I
haven't seen this behavior explained precisely in the .net world yet,
so I wanted to check and make sure I've got it right.

I apologize that this is a bit long. I've tried to keep it concise.
There are code fragments here, but you should be able to scan through
without actually cutting, pasting and running it.

I've got a class, DataHider, with one private string field (i.e.,
private, non-shared module-level variable of type string). DataHider
also has simple public getter and setter methods for the field, which
do nothing other than retrieve or set the values. It's simple because
it's just for testing.

Then I've got a module with two nearly-identical routines, that only
differ by how the parameters are passed to it:

Public Sub callObjectMethodPassedByVal(ByVal myObj As
DataHider)
myObj.setMyData("abcdef")
End Sub

Public Sub callObjectMethodPassedByRef(ByRef myObj As
DataHider)
myObj.setMyData("abcdef")
End Sub

The counterintuitive thing (at least to me) is that *both* of these
routines succeed in changing the data value in myObj, as you can test
with this code fragment if you like:

Private Sub Button2_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button2.Click
Dim hider As New DataHider
Debug.WriteLine("**** Test 2 ****")
hider.setMyData("fred")
Debug.WriteLine("Initial data is: " & hider.getMyData)
objectByVal(hider)
Debug.WriteLine( _
"Data after changing in a sub called byVal is: " _
& hider.getMyData)
objectByRef(hider)
Debug.WriteLine( _
"Data after changing in a sub called byRef is: " _
& hider.getMyData)

End Sub

This routine ends up printing the following in the output window:
**** Test 2 ****
Initial data is: fred
Data after changing in a sub called byVal is: abcdef
Data after changing in a sub called byRef is: abcdef

*****************
I would have thought that an object passed in byVal couldn't be
changed. Now it seems that it all depends on what you mean by "change"
(and perhaps, what "is" is...) It seems that thinking of byVal as
meaning that the called routine works on a "copy" of the passed in
object is at best misleading.

My explanation (please tell me if this is accurate) is that
When you pass an object by value, you are essentially passing its
*address*, and the address is the part that can't be changed. How is
this different than passing byRef? I think that the difference only
shows up when you try to reassign the passed in parameter to another
object (i.e, issue a "myObj = whatever" statement). As long as you
don't do that, it appears to me that byRef and byVal function more or
less identically.

****************
More tests:

reassign the object before changing the data value:
Public Sub objectByVal3(ByVal myObj As DataHider)
myObj = New DataHider 'This is new
myObj.setMyData("abcdef")
End Sub
Public Sub objectByRef3(ByRef myObj As DataHider)
myObj = New DataHider 'This is new
myObj.setMyData("abcdef")
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
Dim hider As New DataHider
Debug.WriteLine("**** Test 3 ****")
hider.setMyData("fred")
Debug.WriteLine("Initial data is: " & hider.getMyData)
objectByVal3(hider)
Debug.WriteLine( _
"Data after changing in a sub called byVal is: " _
& hider.getMyData)
objectByRef3(hider)
Debug.WriteLine( _
"Data after changing in a sub called byRef is: " _
& hider.getMyData)
End Sub

**** Test 3 ****
Initial data is: fred
Data after changing in a sub called byVal is: fred
Data after changing in a sub called byRef is: abcdef

I think this evidence tends to confirm my theory.

************************************************** ****
One more tiny, but fascinating test:

In a single module, declare
private m_hider as DataHider

and the following two routines:

Public Sub objectByVal4(ByVal myObj As DataHider)
Debug.WriteLine(myObj Is m_hider)
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button4.Click
Debug.WriteLine("**** Test 4 ****")
m_hider = New DataHider 'm_hider has to be declared at module
'level
objectByVal4(m_hider)
End Sub
When you call objectByVal4 from the Click event as above, it prints
"True". I find this to be massively counterintuitive, unless you think
of byVal as a copy of the address of the object. In that view, it makes
perfect sense that if you add "myObj = New DataHider" before the
debug.writeline, you will then get a False printout in the output
window. That is, in fact, what occurs.

I'd appreciate any corrections or clarifications to this
conceptualization of the difference between the two passing methods.

Thanks,
Warren
Nov 21 '05 #1
4 2433
Warren,
ByVal & ByRef Parameters are independent of Reference & Value Types. All
parameters in VB.NET by default are passed ByVal, you should only pass a
parameter ByRef when you have to, which is when you need to modify the
callers variable.

A Reference Type is an object that exists on the heap. If I have a variable
that is a reference type and assign the variable to another variable. Both
variables will be pointing to the same object on the heap.

Dim x As Person
x = New Person()
Dim y As Person
y = x

Both x & y are the exact same Person object on the heap.

A Value Type does not live on the Heap. If I have a value type variable and
I assign it to another variable, a copy of the value is made.

Dim x As Integer
x = 100
Dim y As Integer
y = x

Although both x & y have the value 100, they are physically different values
as a copy was made.

Now when you pass a variable to a ByVal parameter a copy of the variable is
made. So for a Reference Type a copy of the reference is made, which means
there is still only one object on the heap & two references to that object.
For a Value Type a copy of the value is made.

When you pass a variable to a ByRef parameter a reference to that variable
is made. So for a Reference Type you have a reference to a reference to the
object, for a Value Type you have a reference to the value.

Remember ByVal & ByRef are how parameters are passed. Reference & Value
Types are how quantities are stored.

The following site also does a good job of explaining Reference & Value
types & ByRef & ByVal parameters.

http://www.yoda.arachsys.com/csharp/parameters.html
Hope this helps
Jay
"Warren Sirota" <ws*****@wsdesigns.com> wrote in message
news:ee**************@TK2MSFTNGP10.phx.gbl...
Hi,

Please let me know if I am interpreting this correctly. I've done a
little testing of the difference between passing parameters byVal and
byRef, and the results were slightly non-intuitive, as I expected. I
haven't seen this behavior explained precisely in the .net world yet,
so I wanted to check and make sure I've got it right.

I apologize that this is a bit long. I've tried to keep it concise.
There are code fragments here, but you should be able to scan through
without actually cutting, pasting and running it.

I've got a class, DataHider, with one private string field (i.e.,
private, non-shared module-level variable of type string). DataHider
also has simple public getter and setter methods for the field, which
do nothing other than retrieve or set the values. It's simple because
it's just for testing.

Then I've got a module with two nearly-identical routines, that only
differ by how the parameters are passed to it:

Public Sub callObjectMethodPassedByVal(ByVal myObj As
DataHider)
myObj.setMyData("abcdef")
End Sub

Public Sub callObjectMethodPassedByRef(ByRef myObj As
DataHider)
myObj.setMyData("abcdef")
End Sub

The counterintuitive thing (at least to me) is that *both* of these
routines succeed in changing the data value in myObj, as you can test
with this code fragment if you like:

Private Sub Button2_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button2.Click
Dim hider As New DataHider
Debug.WriteLine("**** Test 2 ****")
hider.setMyData("fred")
Debug.WriteLine("Initial data is: " & hider.getMyData)
objectByVal(hider)
Debug.WriteLine( _
"Data after changing in a sub called byVal is: " _
& hider.getMyData)
objectByRef(hider)
Debug.WriteLine( _
"Data after changing in a sub called byRef is: " _
& hider.getMyData)

End Sub

This routine ends up printing the following in the output window:
**** Test 2 ****
Initial data is: fred
Data after changing in a sub called byVal is: abcdef
Data after changing in a sub called byRef is: abcdef

*****************
I would have thought that an object passed in byVal couldn't be
changed. Now it seems that it all depends on what you mean by "change"
(and perhaps, what "is" is...) It seems that thinking of byVal as
meaning that the called routine works on a "copy" of the passed in
object is at best misleading.

My explanation (please tell me if this is accurate) is that
When you pass an object by value, you are essentially passing its
*address*, and the address is the part that can't be changed. How is
this different than passing byRef? I think that the difference only
shows up when you try to reassign the passed in parameter to another
object (i.e, issue a "myObj = whatever" statement). As long as you
don't do that, it appears to me that byRef and byVal function more or
less identically.

****************
More tests:

reassign the object before changing the data value:
Public Sub objectByVal3(ByVal myObj As DataHider)
myObj = New DataHider 'This is new
myObj.setMyData("abcdef")
End Sub
Public Sub objectByRef3(ByRef myObj As DataHider)
myObj = New DataHider 'This is new
myObj.setMyData("abcdef")
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
Dim hider As New DataHider
Debug.WriteLine("**** Test 3 ****")
hider.setMyData("fred")
Debug.WriteLine("Initial data is: " & hider.getMyData)
objectByVal3(hider)
Debug.WriteLine( _
"Data after changing in a sub called byVal is: " _
& hider.getMyData)
objectByRef3(hider)
Debug.WriteLine( _
"Data after changing in a sub called byRef is: " _
& hider.getMyData)
End Sub

**** Test 3 ****
Initial data is: fred
Data after changing in a sub called byVal is: fred
Data after changing in a sub called byRef is: abcdef

I think this evidence tends to confirm my theory.

************************************************** ****
One more tiny, but fascinating test:

In a single module, declare
private m_hider as DataHider

and the following two routines:

Public Sub objectByVal4(ByVal myObj As DataHider)
Debug.WriteLine(myObj Is m_hider)
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button4.Click
Debug.WriteLine("**** Test 4 ****")
m_hider = New DataHider 'm_hider has to be declared at module
'level
objectByVal4(m_hider)
End Sub
When you call objectByVal4 from the Click event as above, it prints
"True". I find this to be massively counterintuitive, unless you think
of byVal as a copy of the address of the object. In that view, it makes
perfect sense that if you add "myObj = New DataHider" before the
debug.writeline, you will then get a False printout in the output
window. That is, in fact, what occurs.

I'd appreciate any corrections or clarifications to this
conceptualization of the difference between the two passing methods.

Thanks,
Warren

Nov 21 '05 #2
Warren,
ByVal & ByRef Parameters are independent of Reference & Value Types. All
parameters in VB.NET by default are passed ByVal, you should only pass a
parameter ByRef when you have to, which is when you need to modify the
callers variable.

A Reference Type is an object that exists on the heap. If I have a variable
that is a reference type and assign the variable to another variable. Both
variables will be pointing to the same object on the heap.

Dim x As Person
x = New Person()
Dim y As Person
y = x

Both x & y are the exact same Person object on the heap.

A Value Type does not live on the Heap. If I have a value type variable and
I assign it to another variable, a copy of the value is made.

Dim x As Integer
x = 100
Dim y As Integer
y = x

Although both x & y have the value 100, they are physically different values
as a copy was made.

Now when you pass a variable to a ByVal parameter a copy of the variable is
made. So for a Reference Type a copy of the reference is made, which means
there is still only one object on the heap & two references to that object.
For a Value Type a copy of the value is made.

When you pass a variable to a ByRef parameter a reference to that variable
is made. So for a Reference Type you have a reference to a reference to the
object, for a Value Type you have a reference to the value.

Remember ByVal & ByRef are how parameters are passed. Reference & Value
Types are how quantities are stored.

The following site also does a good job of explaining Reference & Value
types & ByRef & ByVal parameters.

http://www.yoda.arachsys.com/csharp/parameters.html
Hope this helps
Jay
"Warren Sirota" <ws*****@wsdesigns.com> wrote in message
news:ee**************@TK2MSFTNGP10.phx.gbl...
Hi,

Please let me know if I am interpreting this correctly. I've done a
little testing of the difference between passing parameters byVal and
byRef, and the results were slightly non-intuitive, as I expected. I
haven't seen this behavior explained precisely in the .net world yet,
so I wanted to check and make sure I've got it right.

I apologize that this is a bit long. I've tried to keep it concise.
There are code fragments here, but you should be able to scan through
without actually cutting, pasting and running it.

I've got a class, DataHider, with one private string field (i.e.,
private, non-shared module-level variable of type string). DataHider
also has simple public getter and setter methods for the field, which
do nothing other than retrieve or set the values. It's simple because
it's just for testing.

Then I've got a module with two nearly-identical routines, that only
differ by how the parameters are passed to it:

Public Sub callObjectMethodPassedByVal(ByVal myObj As
DataHider)
myObj.setMyData("abcdef")
End Sub

Public Sub callObjectMethodPassedByRef(ByRef myObj As
DataHider)
myObj.setMyData("abcdef")
End Sub

The counterintuitive thing (at least to me) is that *both* of these
routines succeed in changing the data value in myObj, as you can test
with this code fragment if you like:

Private Sub Button2_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button2.Click
Dim hider As New DataHider
Debug.WriteLine("**** Test 2 ****")
hider.setMyData("fred")
Debug.WriteLine("Initial data is: " & hider.getMyData)
objectByVal(hider)
Debug.WriteLine( _
"Data after changing in a sub called byVal is: " _
& hider.getMyData)
objectByRef(hider)
Debug.WriteLine( _
"Data after changing in a sub called byRef is: " _
& hider.getMyData)

End Sub

This routine ends up printing the following in the output window:
**** Test 2 ****
Initial data is: fred
Data after changing in a sub called byVal is: abcdef
Data after changing in a sub called byRef is: abcdef

*****************
I would have thought that an object passed in byVal couldn't be
changed. Now it seems that it all depends on what you mean by "change"
(and perhaps, what "is" is...) It seems that thinking of byVal as
meaning that the called routine works on a "copy" of the passed in
object is at best misleading.

My explanation (please tell me if this is accurate) is that
When you pass an object by value, you are essentially passing its
*address*, and the address is the part that can't be changed. How is
this different than passing byRef? I think that the difference only
shows up when you try to reassign the passed in parameter to another
object (i.e, issue a "myObj = whatever" statement). As long as you
don't do that, it appears to me that byRef and byVal function more or
less identically.

****************
More tests:

reassign the object before changing the data value:
Public Sub objectByVal3(ByVal myObj As DataHider)
myObj = New DataHider 'This is new
myObj.setMyData("abcdef")
End Sub
Public Sub objectByRef3(ByRef myObj As DataHider)
myObj = New DataHider 'This is new
myObj.setMyData("abcdef")
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
Dim hider As New DataHider
Debug.WriteLine("**** Test 3 ****")
hider.setMyData("fred")
Debug.WriteLine("Initial data is: " & hider.getMyData)
objectByVal3(hider)
Debug.WriteLine( _
"Data after changing in a sub called byVal is: " _
& hider.getMyData)
objectByRef3(hider)
Debug.WriteLine( _
"Data after changing in a sub called byRef is: " _
& hider.getMyData)
End Sub

**** Test 3 ****
Initial data is: fred
Data after changing in a sub called byVal is: fred
Data after changing in a sub called byRef is: abcdef

I think this evidence tends to confirm my theory.

************************************************** ****
One more tiny, but fascinating test:

In a single module, declare
private m_hider as DataHider

and the following two routines:

Public Sub objectByVal4(ByVal myObj As DataHider)
Debug.WriteLine(myObj Is m_hider)
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button4.Click
Debug.WriteLine("**** Test 4 ****")
m_hider = New DataHider 'm_hider has to be declared at module
'level
objectByVal4(m_hider)
End Sub
When you call objectByVal4 from the Click event as above, it prints
"True". I find this to be massively counterintuitive, unless you think
of byVal as a copy of the address of the object. In that view, it makes
perfect sense that if you add "myObj = New DataHider" before the
debug.writeline, you will then get a False printout in the output
window. That is, in fact, what occurs.

I'd appreciate any corrections or clarifications to this
conceptualization of the difference between the two passing methods.

Thanks,
Warren

Nov 21 '05 #3
Jay:

That's a terrific reference. Thanks so much.

Warren
Jay B. Harlow [MVP - Outlook] wrote:

The following site also does a good job of explaining Reference &
Value types & ByRef & ByVal parameters.

http://www.yoda.arachsys.com/csharp/parameters.html
Hope this helps
Jay

Nov 21 '05 #4
Jay:

That's a terrific reference. Thanks so much.

Warren
Jay B. Harlow [MVP - Outlook] wrote:

The following site also does a good job of explaining Reference &
Value types & ByRef & ByVal parameters.

http://www.yoda.arachsys.com/csharp/parameters.html
Hope this helps
Jay

Nov 21 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Mike | last post by:
Hi All, I have been struggling with this for weeks now and I just can't get my head around it. I am trying to convert this procedure to VB.NET. In particular I am having problems with the...
8
by: Sandy | last post by:
Hello! Help!!!! I have ten zillion books that attempt to describe the difference between ByVal and ByRef and none of them are clear to me. I have gathered that ByVal makes a copy and ByRef...
5
by: john | last post by:
Here is the short story of what i'm trying to do. I have a 4 sided case labeling printer setting out on one of our production lines. Now then i have a vb.net application that sends data to this...
7
by: Hei | last post by:
Hi, i know the difference of ByRef and ByVal, in case if use byref or byval don't affect the result which one should prefer? (less memory use, better performance ....issue) thx
2
by: John Regan | last post by:
Hello All I am trying to find the owner of a file or folder on our network (Windows 2000 Server) using VB.Net and/or API. so I can search for Folders that don't follow our company's specified...
14
by: Robin Tucker | last post by:
Although I've been working on this project for 8 months now, I'm still not sure of the difference between ByVal and ByRef. As most objects in VB are reference types, passing ByVal I've discovered...
0
by: Warren Sirota | last post by:
Hi, Please let me know if I am interpreting this correctly. I've done a little testing of the difference between passing parameters byVal and byRef, and the results were slightly non-intuitive,...
1
by: Terrance | last post by:
Hello, I was wondering if someone can help me understand something. Below is some code that I got from the MS website that is suppose to authenticate for the username and password on the local...
0
by: Vayse | last post by:
I found this code on the MSDN site, from a post thats about a year old. It does seem to work. However, I'm confused in how to use the impersonated user. I'd like to use impersonatedUser to run...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.