18 Oct 2010

A few days ago, I had a question at work on why “regular” objects could be modified when in a method, while strings couldn’t. That’s a good question that any C#/Java developer (and many other languages) will ask at some point.

The issue there is the general misunderstanding about parameter passing in C#. My response to that is generally to say that “In C#, all parameters are passed by value”. Which is wrong if you include ref and out modifiers, but I won’t cover these in this post. I say it that way because it makes people think about it. Generally the first answer is “No because I can modify an object in a method!”.

That’s when you realize that most of the people understand the logic, but have issues being precise on telling what is truly happening. It has to do with the fact that strings are reference types in .NET. Taken from MSDN:

Variables of reference types, referred to as objects, store references to the actual data.

To get with my previous statement, the value of a reference variable is the reference to the actual data. Also, the actual data will be stored on the heap, but this is implementation details that we should not take into account.

So, to sum it up, when you pass a variable of reference type to a method, you actually pass the reference itself, as a value, to the method.

Here is very simple sample of code to illustrate all of that:

static void Main()
{
    String name = "Philippe";

    Console.WriteLine(name);

    Modify(name);

    Console.WriteLine(name);

    Console.ReadLine();
}

static void Modify(String text)
{
    Console.WriteLine(text);

    text = "Hello";

    Console.WriteLine(text);
}

And here is the printout for this:

Philippe

Philippe

Hello

Philippe

Let’s examine the memory during the different phases.

Here is the memory just before the call to Modify:

Memory1

Now, here is the memory when entering Modify:

Memory2

We can see that both text and name variables have the same value, namely the reference to a location in the heap that contains a string which content is “Philippe”.

Now, with that picture in mind, it’s very easy to imagine what will happen when we change the value of text:

Memory3

As simple as that. We modified the value of text, assigning it the reference to a string containing “Hello” somewhere in the heap. But we didn’t modify the name variable nor it’s content.

When we exit the Modify method, text variable gets out of scope and is eligible for garbage collection. The name variable was not modified in the process.

Now, this confusion also arises because of the fact that string are immutable. Mutable object’s internal content can be modified if you have a reference to them, but this does not hold true for immutable reference objects as you don’t modify them, you create new.

For a very good extensive tutorial on this topic, please see Jon Skeet’s excellent article on the subject. It’s probably much more clear that what I can explain.



blog comments powered by Disqus