Download
Time and again I have heard that in C#, method arguments are passed based upon there type. i.e. Value types are passed by value and reference types are passed by reference. This is so untrue. Reference types have nothing to do with pass by value.
Let us talk some basic. Consider the assignment first. When you assign a value type to another its value is copied. This is because value type variable contains its data directly. When you assign a reference type variable to another only the reference gets copied. This is because a reference type variable does not contains its data directly. It only holds reference to data.
Thus, when we pass a value type, its value gets copied and when we pass a reference type its reference gets copied. That is why if we change the value of a value type variable in the block (method), the change is not seen outside of it. On the other hand if we change the value of member of reference passed to the block from within the block the change persists outside the block.
Ok ! OK!
Some of you may say that, that is why reference types are passed by reference.
Wait! Wait!
Try changing the reference itself. You won't be able to do that. So actually you changed the value on the heap which was being pointed by the reference variable but you were not able to change the variable. Now, try using out or ref keywords and create a new reference type variable from within the block. You will succeed.
Actually when we are passing reference type without using out or ref we are passing just a pointer and that is why if we are trying to use new (to create a new object) we were not able to do that. On the other hand when we passed them using out or ref we passed pointer to pointer and that is why we were able to change the pointer being pointed using the new keyword.
Thus, we can safely say that in each case we changed the value being pointed by the reference and were not able to change the argument.
using System;
using System.Threading;
namespace ArgumentsPassByValue
{
class Program
{
static void Main(string[] args)
{
Worker worker = new Worker();
Request request = new Request();
request.Id = 4;
Console.WriteLine(request.Id + " : " + request.GetHashCode());
worker.PassByReference(ref request);
Console.WriteLine(request.Id + " : " + request.GetHashCode());
//first request object will be collected as it is not being used
GC.Collect();
//forced thred to sleep so that you can see that first object has been
//collected and still we are using the variable request because it is pointing to some other location now.
Thread.Sleep(1000);
Console.WriteLine(request.Id + " : " + request.GetHashCode());
Console.ReadLine();
}
}
internal class Request
{
public int Id { get; set; }
~Request()
{
Console.WriteLine(this.GetHashCode() + " : I am dying");
}
}
internal class Worker
{
public void PassByReference(ref Request request)
{
request = new Request();
request.Id = 6;
}
public void ValueChanger(Request request)
{
Console.WriteLine(request.Id + " : " + request.GetHashCode());
request = new Request();
request.Id = 6;
}
}
}
Some more references :
http://msdn.microsoft.com/en-us/library/s6938f28.aspx
Comments
Post a Comment