我知道,如果我传递一个值类型(int, struct等)作为参数(没有ref关键字),该变量的副本将传递给方法,但如果我使用ref关键字,则传递对该变量的引用,而不是一个新变量。

但是对于引用类型,就像类一样,即使没有ref关键字,也会将引用传递给方法,而不是副本。那么ref关键字与reference-types有什么用呢?


举个例子:

var x = new Foo();

以下两种有什么区别?

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

and

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

当前回答

引用变量携带地址从一个地方到另一个地方,所以任何地方对它们的更新都会反映到所有地方,那么REF有什么用。 引用变量(405)是有效的,直到没有新的内存分配给在方法中传递的引用变量。

一旦分配了新的内存(410),那么这个对象(408)上的值变化将不会反映在所有地方。 裁判来了。Ref是引用的引用,所以每当分配新的内存时,它就会知道,因为它指向那个位置,因此这个值可以被每个人共享。您可以更清楚地看到图像。

其他回答

在某些情况下,你想修改实际的引用,而不是所指向的对象:

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]);

你可以用y来改变foo指向的东西:

Foo foo = new Foo("1");

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

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

这里解释得很好: http://msdn.microsoft.com/en-us/library/s6938f28.aspx

文章摘要:

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.

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.

值类型: 标识符(包含值=堆栈值的地址)---->值类型的值

引用类型: 标识符(包含值=堆栈值的地址)---->(包含值=堆值的地址)---->堆值(通常包含到其他值的地址),想象更多的箭头指向数组[0],数组[1],数组[2]

更改值的唯一方法是遵循箭头。如果一个箭头丢失/改变了该值不可达的方式。

它允许您修改传入的引用。如。

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

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

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

如果你不关心传入的引用,你也可以使用out:

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

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