我正在寻找一个清晰,简洁和准确的答案。
理想情况下,作为实际答案,尽管欢迎提供指向良好解释的链接。
这也适用于VB.Net,但关键字不同-ByRef和ByVal。
默认情况下(在C#中),将对象传递给函数实际上是将引用的副本传递给该对象。更改参数本身只会更改参数中的值,而不会更改指定的变量。
1 2 3 4 5 6 7 8
| void Test1(string param)
{
param ="new value";
}
string s1 ="initial value";
Test1(s1);
// s1 =="initial value" |
使用out或ref传递对函数调用中指定的变量的引用。对out或ref参数的值所做的任何更改都将传递回调用方。
out和ref的行为相同,只是有一点点区别:ref参数在调用之前需要初始化,而out参数可以未初始化。通过扩展,保证ref参数在方法开始时被初始化,而out参数被视为未初始化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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指出的,out和ref之间的差异仅由C#编译器而不是CLR强制执行。据我所知,VB没有out的等效项,并且仅实现ref(作为ByRef),与CLR的支持相匹配。
关于ref vs. out的另一条注释:两者之间的区别由C#编译器强制执行。 CLR不区分out和ref。这意味着您不能有两种方法的签名仅因out或ref的不同而不同
1 2 3 4 5 6 7 8 9
| 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) {} |
out表示参数将通过以下方法初始化:
1 2 3 4 5 6 7
| 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将强制传递基础引用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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 |
我在stackoverflow上遇到的一个问题也解决了这个问题。
它处理不同类型的语言中的"按引用传递"和"按值传递",其中包含c#,因此也许您也可以在那里找到一些额外的信息。
基本上可以归结为:
-
ref:带有ref关键字的参数将通过引用传递
-
out:带有out关键字的参数将被视为输出参数
但这实际上是您可以提供的最基本的答案,因为它比这里说明的要复杂一些