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

C# 为什么我需要在声明和调用中使用ref关键字?,c#,keyword,ref,C#,Keyword,Ref,副本: 为什么我需要在声明和调用中使用'ref'关键字 void foo(ref int i) { } 例如,考虑上面函数。如果我不使用ref关键字as调用它 foo(k); 它会给我一个错误: 参数“1”必须与 “ref”关键字 为什么仅在方法签名中指定还不够?这是因为ref指示应通过引用传入参数。它有点像C中的指针++ 比如, void CalFoo() { var i=10; foo(ref i); //i=11 } void foo(ref int i) { i++

副本:

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

void foo(ref int i)
{

}

例如,考虑上面函数。如果我不使用ref关键字as调用它

foo(k);
它会给我一个错误:

参数“1”必须与 “ref”关键字


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

这是因为
ref
指示应通过引用传入参数。它有点像C中的指针++

比如,

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


我想你可以在一个类中同时使用
foo(refint)
foo(int)
。因此,如果不指定
ref
。。编译器如何知道调用哪个方法?

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

因为方法和调用方可能彼此“远离”(不同的程序集,您甚至可能没有包含该方法的程序集的源),必须明确指定out和ref有助于明确意图。因此,这是用户真正知道自己在做什么的事情,而不是技术上的需要。

虽然
ref
在大多数情况下都可以从方法签名推断出来,但它始终是强制性的,因为它可以在方法调用后完全改变代码的行为。考虑:

string hello = "world";
MyMethod(ref hello);
Console.WriteLine(hello);
如果
ref
关键字不在那里,您总是希望代码打印出“world”,而实际上,它可以打印任何东西。

(如前所述,这是一个重复。)

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

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方法来说是一个很好的折衷方案,但我很高兴它不是普通托管代码的折衷方案。

我还听说(或者在某个地方读到——myaybe,这是在对语言设计师的采访中)原因(就像C#中的许多其他“特性”)是是提醒程序员他要调用的函数通过引用使用参数。

@Ngu Soon Hui:是的,我同意。但是我的问题是为什么我需要在方法调用和声明中使用它。Ngu Soon Hui:非常感谢。。现在我明白为什么了。。将等待更多的答案。。。否则你会摇滚+1因为它们
int
ref int
是不同的类型,也适用于重载。看这个答案的最后一句。如果允许删除
ref
,则方法调用的签名将与调用的方法不同。当然可以解决,除非超载。但它可能会导致各种微妙的错误。您还清楚地知道,当使用
ref
调用方法时,该方法可以更改对象引用。。。NET编译器在后台执行一些非常复杂的重载解析(特别是现在引入了
动态
类型),并且在不明确的情况下会出现错误。使用
ref
关键字更重要的是显式显示方法调用中的值可能会更改。您可以使用签名
int
ref int
int
out int
,但是不能有签名
ref int
out int
@Lennaert:听起来像是一个有效的参数。如果你有,你能给我指一些说明这一点的手册吗?实际上,我找不到关于它的任何东西,但编译器足够聪明,可以推断它应该传递一个ref类型(我假设),这就是我得出结论的原因。也许我说得有点太自信了:)这肯定是答案:很明显,C#的设计师不需要在呼叫站点上使用“ref”(几乎没有其他语言需要它),那么除了让代码更清晰之外,为什么还要使用它呢?(好的,正如Jon Skeet指出的那样,这也是重载的问题,但这是非常罕见的,因为其他.NET语言不能以这种方式重载)这绝对是重复的。现在就找到了…@Jon Skeet:我试着搜索,但没找到。如果它是重复的,我会关闭它。@Jon Skeet:谢谢。。。该线程有更多信息。投票结束。不是我添加了参考资料,但这是我想的问题:)你是对的,乔恩。。这是我的复制品。我也投票决定关闭它。顺便说一句,你也回答了这个问题。谢谢。@Jon:Btw,我在读了你的this()文章后有了这个问题。@Mahin:反馈很好-如果我记得的话,我会尝试在那篇文章中添加一个部分。
MyType tmp = x;
ComMethod (ref tmp);