Sunday, October 02, 2005

ByVal and ByRef

We all deal with passing parameter ByVal and ByRef and as we all know that if we pass a variable byval to a routine and if the called routine changes the variable value, it does not reflect in the caller routine, opposite happen in case of byref.

But what happen in case of passing reference type as byval or byref … let us consider the following example..

I have a class named TestClass and which have a public property Name , then all I will do in a win form is create 2 routines which will takes instance of this class as a parameter, first one will take as byval, second one as byref.

private void UpdateTestClassName( TestClass objTestClass )
{
objTestClass.Name = "Neo";
}

private void UpdateTestClassName( ref TestClass objTestClass )
{
objTestClass.Name = "Neo";
}

Then I will add 2 buttons( ByVal and ByRef ) on the form and in the click event of one of them will call the both routines. Like this …

private void btnByVal_Click(object sender, System.EventArgs e)
{
TestClass objTestClass = new TestClass();
objTestClass.Name = "Palb";
Console.WriteLine( objTestClass.Name );
UpdateTestClassName( objTestClass );
try
{
Console.WriteLine( objTestClass.Name );
}
catch( System.NullReferenceException ex )
{
Console.WriteLine( ex.Message );
}
}

private void btnByRef_Click(object sender, System.EventArgs e)
{
TestClass objTestClass = new TestClass();
objTestClass.Name = "Palb";
Console.WriteLine( objTestClass.Name );
UpdateTestClassName( objTestClass );
try
{
Console.WriteLine( objTestClass.Name );
}
catch( System.NullReferenceException ex )
{
Console.WriteLine( ex.Message );
}
}

If we click on ByVal button the output will be following
Palb
Neo

And if we click on the ByRef button the output will be following ..
Palb
Neo

So it seems byVal and byRef behave in same manner in case of Reference type , why is it happening … let us look at what happen inside ..

Data for Reference types is stored on the heap and a pointer (which points to the data on the heap) is created on the stack, whenever an instance of reference type is created the pointer is returned back and is used to manipulate the data on the stack. Hence TestClass objTestClass = new TestClass(); actually returns back the pointer.

Now when this pointer is passed by val, all we are doing is duplicating the pointer but it still points to the same memory on the heap and hence any manipulation done to the object in the called method will manipulate the same data to which original TestClass pointer was pointing. In case of passing by ref, the original pointer itself is passed to the called function,

Now some more interesting facts , let us add one more line to the UpdateTestClassName routines( both byVal and byRef )
objTestClass = null;

Now guess what will the put out …
By Val click will be same , but By Ref click will be
Palb
Object reference not set to an instance of an object.

As we in case of ByRef we pass the original pointer hence if we set objTestClass = null, the original pointer get destroyed( in case of byVal the original pointer still exists, hence it shows the updated value in heap ), hence we will get an NullReferenceException.
Isn’t it interesting ??

1 comment:

Neo said...

ahh .. I made a silly mistake .. in the btnRef_Click event .. I coded ...
UpdateTestClassName( objTestClass );

which will be like this ..

UpdateTestClassName( ref objTestClass );

Neo