Thursday, February 24, 2011

.Net - Value Type and Reference Type

Summary of the Article
Always pass Reference Type ByVAL and not ByRef. Why ? Read it
One of the most common mistakes developers make when learning .NET is confusing Reference and Value Types with Passing values by Reference or Value.

Is this a big deal?  YES!  It's a very big deal.

So let's go through the basics first:

Values types break down like this...

(From MSDN)

Value types include:

     All numeric data types
     Boolean, Char, and Date
     All structures, even if their members are reference types
     Enumerations, since their underlying type is always Byte, Short, Integer, or Long
Reference types include:
     All arrays, even if their elements are value types
     Class types, such as Form

So, when you pass arguments to a subroutine or function, you absolutely must know whether the type is a value type or a reference type. Only then can you determine whether you want to use ByVal or ByRef to pass the data

Value type, passed by value:

This is the simplest of all the possibilities. A value type holds the data itself, not a reference to it. And, when that value type is passed by value, a copy of that data is passed. The subroutine/function cannot change the value of this variable back in the calling routine.
Behind the scenes, a copy of the variable's value is passed on the stack.

Value type, passed by reference:

This is also pretty straightforward. The variable holds the actual data, but when it is passed, a reference variable is created that points to the data. That way, changes to the variable are reflected back in the calling routine. Behind the scenes, this means that a pointer to the data is passed on the stack to the calling routine.

Reference type, passed by value:

A reference type is one that is always manipulated using pointers. So, the value is always in the heap. If you pass a reference type by value, what you are really doing is passing the pointer by value, not the variable itself. This, counter-intuitively, means that you can, in fact, make changes to the data and those changes are reflected back in the calling routine—despite the fact that the data was passed ByVal. So, if ByVal doesn't work like you'd expect with reference types, how do you pass a reference type variable to a subroutine/function and prevent it from being changed back in the calling routine? You can't. (At least not without significant rework...)

Reference type, passed by reference:

As I've already said, a reference type is one that is always referred to using a pointer. So, what happens when you specify that a reference type be passed ByRef? Well, it does exactly what you told it to—it makes a new reference variable that points to the reference variable that points to the data. It's a pointer to a pointer. If you come from a C/C++ background, you know that this type of thing can get really complicated really fast. Fortunately, VB.NET handles all the de-referencing for you and keeps it as simple as possible.

So, the upshot is you can modify the data in a reference type passed by reference. But that's no surprise—you could modify the data in a reference type passed by value. Because of this and because of the unnecessary additional complexity incurred when using pointers to pointers, you should typically avoid this situation altogether. In other words, typically, you should always pass reference variables by value. Just be aware that they can be modified!


No comments:

Post a Comment