Reference and Value Types

Today I’m going to cover some basics in C# – the difference between Reference and Value types.

Here’s a basic example method:

static void DoSomething(int i)
{
    Console.WriteLine("Inside DoSomething(int), before assignment, i is " + i);
    i = 42;
    Console.WriteLine("Inside DoSomething(int), after assignment, i is " + i);
}

and here is the calling code:

int i = 26;
Console.WriteLine("In Main, before calling DoSomething, i is " + i);
DoSomething(i);
Console.WriteLine("In Main, after calling DoSomething, i is *** " + i + " ***");

and the results are:

In Main, before calling DoSomething, i is 26
Inside DoSomething(int), before assignment, i is 26
Inside DoSomething(int), after assignment, i is 42
In Main, after calling DoSomething, i is *** 26 ***

So, the call to the function does not change the value of the variable ‘i’. It was copied when it was passed as a parameter, the method changed the copy, meanwhile the calling function still had it’s own copy.

Let’s look at some similar code for a class. Here’s the class:

public class Class
{
    int _member;

    public int Member
    {
        get { return _member; }
        set { _member = value; }
    }
}

Note the class contains only an integer in this example, so it could be considered a wrapper for the integer. Here’s the ‘same’ method that adjusts the member of the class:

static void DoSomething(Class c)
{
    Console.WriteLine("Inside DoSomething(Class), before assignment, c.Member is " + c.Member);
    c.Member = 42;
    Console.WriteLine("Inside DoSomething(Class), after assignment, c.Member is " + c.Member);
}

and now the calling code:

c.Member = 26;
Console.WriteLine("In Main, before calling DoSomething, c.Member is " + c.Member);
DoSomething(c);
Console.WriteLine("In Main, after calling DoSomething, c.Member is *** " + c.Member + " ***");

Finally, the output:

In Main, before calling DoSomething, c.Member is 26
Inside DoSomething(Class), before assignment, c.Member is 26
Inside DoSomething(Class), after assignment, c.Member is 42
In Main, after calling DoSomething, c.Member is *** 42 ***

The member of the class has retained the value we assigned to it in the method – the class was not copied, but a reference to the class was passed to the method… so the changes to contents of the class are visible outside the method.

Strings behave like Value types

Strings are a class type in C#, but they don’t behave as you might expect:

In Main, before calling DoSomething, s1 is 'Hello from Main'
Inside DoSomething(string), before assignment, s1 is 'Hello from Main'
Inside DoSomething(string), after assignment, s1 is 'Hello from DoSomething!'
In Main, after calling DoSomething, s1 is 'Hello from Main'

Why would a class behave like a value type? The answer is that internally, the string class treats strings as immutable; if you change the string, a new string object is created, the local string in the method points to that, but the caller still points to the original string. Thus, it behaves like a value type.

Sample VS2005 Project

A sample VS2005 project is available here, with the full examples above and more. Reference and Value Types Project

Leave a Reply

Your email address will not be published. Required fields are marked *