What is the use of “ref” for reference-type variab

2019-01-01 10:05发布

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";
}

10条回答
永恒的永恒
2楼-- · 2019-01-01 10:50

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
}
查看更多
公子世无双
3楼-- · 2019-01-01 10:52

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;
    }
}
查看更多
千与千寻千般痛.
4楼-- · 2019-01-01 10:55

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.

查看更多
笑指拈花
5楼-- · 2019-01-01 10:55

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();
}
查看更多
浪荡孟婆
6楼-- · 2019-01-01 10:55

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 are good till no new memory is allocated to the reference variable passed in the method. Once new memory allocate then the value change on this 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

查看更多
呛了眼睛熬了心
7楼-- · 2019-01-01 10:56

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.

查看更多
登录 后发表回答