C# ref、val 和 out 对方法参数的含义是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-01 08:45:07  来源:igfitidea点击:

What do ref, val and out mean on method parameters?

提问by Keith

I'm looking for a clear, concise and accurate answer.

我正在寻找一个清晰、简洁和准确的答案。

Ideally as the actual answer, although links to good explanations welcome.

理想情况下作为实际答案,尽管欢迎提供良好解释的链接。

This also applies to VB.Net, but the keywords are different - ByRefand ByVal.

这也适用于 VB.Net,但关键字不同 -ByRefByVal.

采纳答案by Zooba

By default (in C#), passing an object to a function actually passes a copy of the reference to that object. Changing the parameter itself only changes the value in the parameter, and not the variable that was specified.

默认情况下(在 C# 中),将对象传递给函数实际上是将引用的副本传递给该对象。更改参数本身只会更改参数中的值,而不是指定的变量。

void Test1(string param)
{
    param = "new value";
}

string s1 = "initial value";
Test1(s1);
// s1 == "initial value"

Using outor refpasses a reference to the variable specified in the call to the function. Any changes to the value of an outor refparameter will be passed back to the caller.

使用outref传递对函数调用中指定的变量的引用。对outref参数值的任何更改都将传递回调用方。

Both outand refbehave identically except for one slight difference: refparameters are required to be initialised before calling, while outparameters can be uninitialised. By extension, refparameters are guaranteed to be initialised at the start of the method, while outparameters are treated as uninitialised.

无论outref行为相同,除了一个细微的差别:ref需要参数调用之前被初始化,而out参数可以未初始化。通过扩展,ref参数保证在方法开始时被初始化,而out参数被视为未初始化。

void Test2(ref string param)
{
    param = "new value";
}

void Test3(out string param)
{
    // Use of param here will not compile
    param = "another value";
}

string s2 = "initial value";
string s3;
Test2(ref s2);
// s2 == "new value"
// Test2(ref s3); // Passing ref s3 will not compile
Test3(out s2);
// s2 == "another value"
Test3(out s3);
// s3 == "another value"

Edit: As dppoints out, the difference between outand refis only enforced by the C# compiler, not by the CLR. As far as I know, VB has no equivalent for outand implements ref(as ByRef) only, matching the support of the CLR.

编辑:作为DP指出,之间的差异out,并ref仅由C#编译器执行的,而不是由CLR。据我所知,VB 没有等价物,仅out实现ref(as ByRef),与 CLR 的支持相匹配。

回答by Keith

outmeans that the parameter will be initialised by the method:

out意味着参数将被方法初始化:

int result; //not initialised

if( int.TryParse( "123", out result ) )
   //result is now 123
else
   //if TryParse failed result has still be 
   // initialised to its default value (0)

refwill force the underlying reference to be passed:

ref将强制传递基础引用:

void ChangeMyClass1( MyClass input ) {
   input.MyProperty = "changed by 1";
   input = null;
   //can't see input anymore ... 
   // I've only nulled my local scope's reference
}

void ChangeMyClass2( ref MyClass input ) {
   input.MyProperty = "changed by 2";
   input = null;
   //the passed reference is now null too.
}

MyClass tester = new MyClass { MyProperty = "initial value" };

ChangeMyClass1( tester );
// now tester.MyProperty is "changed by 1"

ChangeMyClass2( ref tester );
// now tester is null

回答by sven

One of my own questions at stackoverflow handles this topic too.
It handles about "pass by reference" and "pass by value"in different types of languages, c# is includedso maybe you can find some extra information there as well.

我自己在 stackoverflow 上的一个问题也处理了这个话题。
它处理不同类型语言中的“按引用传递”和“按值传递”包括 c#,所以也许您也可以在那里找到一些额外的信息。

Basically it comes down to:

基本上归结为:

  • ref: the parameter with the ref keyword will be passed by reference
  • out: the parameter with the out keyword will be treated as an output parameter
  • ref:带有 ref 关键字的参数将通过引用传递
  • out:带有 out 关键字的参数将被视为输出参数

but that's really the most basic answer you can give, as it is a little more complex than it is stated here

但这确实是您可以给出的最基本的答案,因为它比此处说明的要复杂一些

回答by denis phillips

One additional note about ref vs. out: The distinction between the two is enforced by the C# compiler. The CLR does not distinguish between between out and ref. This means that you cannot have two methods whose signatures differ only by an out or ref

关于 ref 与 out 的附加说明:两者之间的区别由 C# 编译器强制执行。CLR 不区分 out 和 ref。这意味着您不能有两个方法的签名仅通过 out 或 ref 不同

void foo(int value) {}

// Only one of the following would be allowed

// valid to overload with ref
void foo(ref int value) {}

// OR with out
void foo(out int value) {}