C# ref keyword usage

The clearest explanation I've ever run across for output and ref parameters is ... Jon Skeet's.

Parameter Passing in C#

He doesn't go into "best practices", but if you understand the examples he's given, you'll know when you need to use them.


When you may replace the original object, you should send him as ref. If it's just for output and can be uninitialized before calling the function, you'll use out.


Put succinctly, you would pass a value as a ref parameter if you want the function you're calling to be able to alter the value of that variable.

This is not the same as passing a reference type as a parameter to a function. In those cases, you're still passing by value, but the value is a reference. In the case of passing by ref, then an actual reference to the variable is sent; essentially, you and the function you're calling "share" the same variable.

Consider the following:

public void Foo(ref int bar)
{
    bar = 5;
}

...

int baz = 2;

Foo(ref baz);

In this case, the baz variable has a value of 5, since it was passed by reference. The semantics are entirely clear for value types, but not as clear for reference types.

public class MyClass
{
    public int PropName { get; set; }
}

public void Foo(MyClass bar)
{
    bar.PropName = 5;
}

...

MyClass baz = new MyClass();

baz.PropName = 2;

Foo(baz);

As expected, baz.PropName will be 5, since MyClass is a reference type. But let's do this:

public void Foo(MyClass bar)
{
    bar = new MyClass();

    bar.PropName = 5;
}

With the same calling code, baz.PropName will remain 2. This is because even though MyClass is a reference type, Foo has its own variable for bar; bar and baz just start out with the same value, but once Foo assigns a new value, they are just two different variables. If, however, we do this:

public void Foo(ref MyClass bar)
{
    bar = new MyClass();

    bar.PropName = 5;
}

...

MyClass baz = new MyClass();

baz.PropName = 2;

Foo(ref baz);

We'll end up with PropName being 5, since we passed baz by reference, making the two functions "share" the same variable.

Tags:

C#