C#中引用类型变量的"ref"有什么用?

And*_*ech 167 c# parameters pass-by-reference pass-by-value

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

但是使用引用类型(如类),即使没有ref关键字,也会将引用传递给方法,而不是副本.那么ref关键字与引用类型的用途是什么?


举个例子:

var x = new Foo();
Run Code Online (Sandbox Code Playgroud)

以下有什么区别?

void Bar(Foo y) {
    y.Name = "2";
}
Run Code Online (Sandbox Code Playgroud)

void Bar(ref Foo y) {
    y.Name = "2";
}
Run Code Online (Sandbox Code Playgroud)

use*_*116 149

您可以更改foo使用的要点y:

Foo foo = new Foo("1");

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

Bar(ref foo);
// foo.Name == "2"
Run Code Online (Sandbox Code Playgroud)

  • 所以你基本上得到了对原始参考的引用 (16认同)
  • 因此在对象上使用'ref'就像在C++中使用双指针一样? (4认同)
  • 您可以更改原始引用"引用"的内容,是的. (2认同)
  • @TomHazel:*-ish*,前提是您在 C++ 中使用“双”指针来更改指针指向的内容。 (2认同)

Meh*_*ari 29

在某些情况下,您希望修改实际引用而不是指向的对象:

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]);
Run Code Online (Sandbox Code Playgroud)


Nol*_*rin 18

Jon Skeet写了一篇关于C#参数传递的精彩文章.它清楚地详细说明了按值,引用(ref)和输出(out)传递参数的确切行为和用法.

以下是该页面中与ref参数相关的重要引用:

引用参数不传递函数成员调用中使用的变量的值 - 它们使用变量本身.不是在函数成员声明中为变量创建新的存储位置,而是使用相同的存储位置,因此函数成员中的变量值和引用参数的值将始终相同.引用参数需要ref修饰符作为声明和调用的一部分 - 这意味着当你通过引用传递某些东西时它总是很清楚.

  • 我喜欢将你的狗皮带传递给朋友以通过参考价值的类比......但它很快就会崩溃,因为我认为你可能会注意到,如果你的朋友将你的shitzu交给一个杜宾犬,然后他才会把你送回去皮带;-) (11认同)

him*_*k66 16

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

摘自文章:

引用类型的变量不直接包含其数据; 它包含对其数据的引用.按值传递reference-type参数时,可以更改引用指向的数据,例如类成员的值.但是,您无法更改引用本身的值; 也就是说,您不能使用相同的引用为新类分配内存并使其在块外部保留.为此,请使用ref或out关键字传递参数.

  • 解释确实非常好.但是,不鼓励在SO上使用纯链接答案.我在文章中添加了一个摘要,为了方便读者. (4认同)

Ryt*_*mis 9

使用ref关键字传递引用类型时,通过引用传递引用,并且调用的方法可以为参数指定新值.该更改将传播到调用范围.如果没有ref,引用将按值传递,这不会发生.

C#也有'out'关键字,它与ref非常相似,除了使用'ref'之外,必须在调用方法之前初始化参数,并且使用'out'必须在接收方法中指定一个值.


HVS*_*HVS 5

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

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

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

    // Overwrite the reference
    y = new Foo();
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用,如果你不关心传入的参考:

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

void Baz(out Foo y)
{
    // Return a new reference
    y = new Foo();
}
Run Code Online (Sandbox Code Playgroud)