为什么我需要在声明和调用中都使用'ref'关键字。
void foo(ref int i)
{
}
例如,考虑上述功能。如果我在没有 ref 关键字的情况下调用它
foo(k);
它会给我错误:
参数 '1' 必须与 'ref' 关键字一起传递
为什么仅在方法签名中指定还不够?
为什么我需要在声明和调用中都使用'ref'关键字。
void foo(ref int i)
{
}
例如,考虑上述功能。如果我在没有 ref 关键字的情况下调用它
foo(k);
它会给我错误:
参数 '1' 必须与 'ref' 关键字一起传递
为什么仅在方法签名中指定还不够?
这是因为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
.. 编译器如何知道要调用哪一个?
它增强了可读性/可理解性:当您查看方法调用时,您知道 ref 值可能会更改。
(如前所述,这是这个问题的骗局。)
一方面,它被用作方法重载的一部分:
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
)时,行为会发生显着变化请注意,C# 4 确实允许隐式使用ref
for COM 方法,因为有很多ref
参数实际上并没有行为(ref
或者至少,它们没有利用它)。在这种情况下,编译器会引入一个新的局部变量,以便从调用者的角度来看,参数实际上是按值传递的:
ComMethod(x);
翻译成:
MyType tmp = x;
ComMethod (ref tmp);
这是对 COM 方法的一个很好的折衷方案,但我很高兴普通托管代码并非如此。
由于方法和调用者可能彼此“远离”(不同的程序集,您甚至可能没有包含该方法的程序集的来源),因此必须明确指定 out 和 ref 有助于明确意图。所以这对用户来说是一件让他们真正知道自己在做什么的东西,而不是技术上的必需品。
虽然ref
大部分时间可以从方法签名中推断出来,但它始终是强制性的,因为它可以在方法调用后完全改变代码的行为。考虑:
string hello = "world";
MyMethod(ref hello);
Console.WriteLine(hello);
如果没有ref
关键字,您总是希望代码打印出“世界”,而实际上,它可以打印任何内容。
我还听说(或在某处读到——也许是在与语言设计师的一次采访中)原因(就像 C# 中的许多其他“功能”一样)是为了提醒程序员他要调用的函数使用参数引用。