Monday, May 11, 2009

Underhood of the "ref" keyword

One of the most interesting keywords in C# is the "ref" keyword. This is a argument parameter, which causes the method (indexer, constructor...) parameters to be passed by reference.
Let's take a look to the following code snippet:

public void TestFunction(int argValue)
{
      argValue++;
}

When we pass an argument to this function a new copy of the argument is being created and the function operates on the copy - not the real object. Because the copy of a reference again points to the sane location, we get no difference using the "ref" keyword with the reference-parameters (in most cases).
Now let's add a ref keyword before the parameter declaration:

public void TestFunction(ref int argValue)
{
      argValue++;
}

In the previous example we will get no result because the ++ operation was done on a copy of the object. But if we now pass the an integer to the function (when calling the function now, already, we have to add the "ref" keyword also here), we will get the increase of the value of the original memory, because this keyword makes the function to operate on the reference of the given parameter.

And here is the most important case. Many developers see no difference in "ref" keyword when using it with reference types. But... let's now review the following interesting example:

public void TestFunction(object argParam)
{
      argParam = null;
}

When entering this function the CLR will create a copy of the reference and will operated on it. But because the copied reference will refer to the same object on the heap, we will get the same result using the object's methods. And when we assign null to the argParam in the function body, we will just remove the copied reference of the parameter, which will take no modification on the real object.

And now, let's add the ref keyword before the param declaration:

public void TestFunction(ref object argParam)
{
      argParam = null;
}

Here comes the specific behavior of the keyword. No copy of the reference is being created during function call, so when we assign a null value to the argument, we remove the original reference from the memory, and ... in the calling context - lose the reference to the object.