22

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

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

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

4

4 回答 4

27

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

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

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

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

两者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"

编辑:正如dp指出的那样,和之间的区别outref由 C# 编译器强制执行,而不是由 CLR 强制执行。据我所知,VB 没有等效的 forout并且仅实现ref(as ByRef),与 CLR 的支持相匹配。

于 2008-08-16T12:06:17.337 回答
8

关于 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) {}
于 2008-08-16T12:32:38.983 回答
3

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)

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
于 2008-08-16T08:49:21.760 回答
2

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

基本上它归结为:

  • ref:带有ref关键字的参数将通过引用传递
  • out:带有 out 关键字的参数将被视为输出参数

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

于 2008-08-16T09:21:35.563 回答