What is the use of "ref" for reference-type variables in C#?

C#ParametersPass by-ReferencePass by-Value

C# Problem Overview


I understand that if I pass a value-type (int, struct, etc.) as a parameter (without the ref keyword), a copy of that variable is passed to the method, but if I use the ref keyword a reference to that variable is passed, not a new one.

But with reference-types, like classes, even without the ref keyword, a reference is passed to the method, not a copy. So what is the use of the ref keyword with reference-types?


Take for example:

var x = new Foo();

What is the difference between the following?

void Bar(Foo y) {
    y.Name = "2";
}

and

void Bar(ref Foo y) {
    y.Name = "2";
}

C# Solutions


Solution 1 - C#

You can change what foo points to using y:

Foo foo = new Foo("1");

void Bar(ref Foo y)
{
    y = new Foo("2");
}

Bar(ref foo);
// foo.Name == "2"

Solution 2 - C#

There are cases where you want to modify the actual reference and not the object pointed to:

void Swap<T>(ref T x, ref T y) {
    T t = x;
    x = y;
    y = t;
}

var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);

Solution 3 - C#

Jon Skeet wrote a great article about parameter passing in C#. It details clearly the exact behaviour and usage of passing parameters by value, by reference (ref), and by output (out).

Here's an important quote from that page in relation to ref parameters:

> Reference parameters don't pass the > values of the variables used in the > function member invocation - they use > the variables themselves. Rather than > creating a new storage location for > the variable in the function member > declaration, the same storage location > is used, so the value of the variable > in the function member and the value > of the reference parameter will always > be the same. Reference parameters need > the ref modifier as part of both the > declaration and the invocation - that > means it's always clear when you're > passing something by reference.

Solution 4 - C#

Very nicely explained here : http://msdn.microsoft.com/en-us/library/s6938f28.aspx

Abstract from the article:

> A variable of a reference type does not contain its data directly; it > contains a reference to its data. When you pass a reference-type > parameter by value, it is possible to change the data pointed to by > the reference, such as the value of a class member. However, you > cannot change the value of the reference itself; that is, you cannot > use the same reference to allocate memory for a new class and have it > persist outside the block. To do that, pass the parameter using the > ref or out keyword.

Solution 5 - C#

When you pass a reference type with the ref keyword, you pass the reference by reference, and the method you call can assign a new value to the parameter. That change will propagate to the calling scope. Without ref, the reference is passed by value, and this doesn't happen.

C# also has the 'out' keyword which is a lot like ref, except that with 'ref', arguments must be initialized before calling the method, and with 'out' you must assign a value in the receiving method.

Solution 6 - C#

It allows you to modify the reference passed in. e.g.

void Bar()
{
    var y = new Foo();
    Baz(ref y);
}

void Baz(ref Foo y)
{
    y.Name = "2";

    // Overwrite the reference
    y = new Foo();
}

You can also use out if you don't care about the reference passed in:

void Bar()
{
    var y = new Foo();
    Baz(out y);
}

void Baz(out Foo y)
{
    // Return a new reference
    y = new Foo();
}

Solution 7 - C#

Another bunch of code

class O
{
    public int prop = 0;
}

class Program
{
    static void Main(string[] args)
    {
        O o1 = new O();
        o1.prop = 1;

        O o2 = new O();
        o2.prop = 2;

        o1modifier(o1);
        o2modifier(ref o2);

        Console.WriteLine("1 : " + o1.prop.ToString());
        Console.WriteLine("2 : " + o2.prop.ToString());
        Console.ReadLine();
    }

    static void o1modifier(O o)
    {
        o = new O();
        o.prop = 3;
    }

    static void o2modifier(ref O o)
    {
        o = new O();
        o.prop = 4;
    }
}

Solution 8 - C#

In addition to the existing answers:

As you asked for the difference of the 2 methods: There is no co(ntra)variance when using ref or out:

class Foo { }
class FooBar : Foo { }

static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }

void Main()
{
	Foo foo = null;
	Bar(foo);			// OK
	Bar(ref foo);		// OK
	
	FooBar fooBar = null;
	Bar(fooBar);		// OK (covariance)
	Bar(ref fooBar);	// compile time error
}

Solution 9 - C#

A parameter in a method seems to be always passing a copy, the question is a copy of what. A copy is done by a copy constructor for an object and since all variables are Object in C#, i believe this is the case for all of them. Variables(objects) are like people living at some addresses. We either change the people living at those addresses or we can create more references to the people living at those addresses in the phone book(make shallow copies). So, more than one identifier can refer to the same address. Reference types desire more space, so unlike value types that are directly connected by an arrow to their identifier in the stack, they have value for another address in the heap( a bigger space to dwell). This space needs to be taken from the heap.

Value type: Indentifier(contains value =address of stack value)---->Value of value type

Reference type: Identifier(contains value=address of stack value)---->(contains value=address of heap value)---->Heap value(most often contains addresses to other values), imagine more arrows sticking in different directions to Array[0], Array[1], array[2]

The only way to change a value is to follow the arrows. If one arrow gets lost/changed in the way the value is unreachable.

Solution 10 - C#

Reference Variables carry the address from one place to another so any updation on them at any place will reflect on all the places THEN what is the use of REF. Reference variable (405) are good till no new memory is allocated to the reference variable passed in the method.

Once new memory allocate (410) then the value change on this object (408) will not reflect everywhere. For this ref comes. Ref is reference of reference so whenever new memory allocate it get to know because it is pointing to that location therefore the value can be shared by everyOne. You can see the image for more clearity.

Ref in Reference Variable

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndreas GrechView Question on Stackoverflow
Solution 1 - C#user7116View Answer on Stackoverflow
Solution 2 - C#mmxView Answer on Stackoverflow
Solution 3 - C#NoldorinView Answer on Stackoverflow
Solution 4 - C#himanshupareek66View Answer on Stackoverflow
Solution 5 - C#RytmisView Answer on Stackoverflow
Solution 6 - C#Hans Van SlootenView Answer on Stackoverflow
Solution 7 - C#SvendView Answer on Stackoverflow
Solution 8 - C#springy76View Answer on Stackoverflow
Solution 9 - C#Petar DrianovView Answer on Stackoverflow
Solution 10 - C#srbhView Answer on Stackoverflow