为什么我需要在声明和调用中使用ref关键字?

时间:2009-10-06 07:30:40

标签: c# keyword ref

重复:What is the purpose of the “out” keyword at the caller?

为什么我需要在声明和呼叫中使用'ref'关键字。

void foo(ref int i)
{

}

例如,考虑以上功能。如果我将其称为没有ref关键字

foo(k);

它会给我错误:

  

参数'1'必须与。一起传递   'ref'关键字

为什么仅仅在方法签名中指定不够?

6 个答案:

答案 0 :(得分:12)

这是因为ref表示该参数应该通过引用传入。它类似于C ++中的指针

例如;

void CalFoo()
{
  var i=10;
  foo(ref i);  //i=11
}
void foo(ref int i)
{
   i++;
}

void CalFoo()
{
  var i=10;
  foo(i);  //i=10
}
void foo(int i)
{
   i++;
}

我认为您可以在一个单独的课程中同时拥有foo(ref int)foo(int)。所以,如果你没有指定ref ..编译器如何知道要调用哪一个?

答案 1 :(得分:9)

它增强了可读性/可理解性:当你查看方法调用时,你知道ref值可能会改变。

答案 2 :(得分:4)

(如上所述,这是this question的欺骗。)

首先,它被用作方法重载的一部分:

public void Foo(string x) { ... }
public void Foo(ref string x) { ... }

...

string x = "";
Foo(x); // Which should be used if you didn't have to specify ref?

现在一个答案可能就是禁止那种超载...但我认为C#在调用者身上需要这个作为文档是一件好事:

  • 使用ref(或out
  • 时,行为会发生显着变化
  • 通过调用ref / out的罕见用法,这意味着您永远不需要检查是否 参数是通过值或引用传递的
  • 它还会影响您可以传递的内容(例如,您无法传递文字或方法调用的结果)。当它明确时,这一点就更清楚了。

请注意,C#4允许对COM方法隐式使用ref,因为有很多ref个参数不会真的具有ref行为(或者至少,他们没有利用它)。在这种情况下,编译器引入了一个新的局部变量,以便从调用者的角度来看,的参数是通过值传递的:

ComMethod(x);

转换为:

MyType tmp = x;
ComMethod (ref tmp);

这是COM方法的一个很好的折衷方案,但我很高兴普通托管代码不是这样。

答案 3 :(得分:3)

由于方法和调用者可能彼此“远离”(不同的程序集,您甚至可能没有包含该方法的源的源),因此必须明确指出并明确地帮助使目标明确。所以这对用户来说是有用的,这样他们才能真正知道他们做了什么,而不是技术上的必需品。

答案 4 :(得分:3)

尽管ref大部分时间都可以从方法签名中推断出来,但由于它可以在完全调用方法之后改变代码的行为,因此它总是必须的。考虑:

string hello = "world";
MyMethod(ref hello);
Console.WriteLine(hello);

如果ref关键字没有出现在那里,您总会希望代码打印出“世界”,而实际上,它可以打印任何内容。

答案 5 :(得分:1)

我也听过(或者在某个地方读过 - 我是在接受语言设计师的采访时),原因(就像C#中的许多其他“功能”一样)是提醒程序员他要调用的功能。通过引用使用参数。