ref,val和out对方法参数意味着什么?
时间:2020-03-05 18:40:03 来源:igfitidea点击:
我正在寻找一个清晰,简洁和准确的答案。
理想情况下,作为实际答案,尽管欢迎提供指向良好解释的链接。
这也适用于VB.Net,但是关键字是" ByRef"和" ByVal"不同。
解决方案
回答
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
回答
我在stackoverflow上遇到的一个问题也处理了该主题。
它处理了不同类型的语言中的"按引用传递"和"按值传递",包括顺式,因此也许我们也可以在那里找到一些其他信息。
基本上可以归结为:
- ref:带有ref关键字的参数将通过引用传递
- out:带有out关键字的参数将被视为输出参数
但这实际上是我们可以提供的最基本的答案,因为它比这里说明的要复杂一些
回答
默认情况下(在C#中),将对象传递给函数实际上是将引用的副本传递给该对象。更改参数本身只会更改参数中的值,而不会更改指定的变量。
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"参数被视为未初始化。
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
之间的区别仅由Ccompiler强制执行,而不由CLR强制执行。据我所知,VB没有等效于out
,并且仅实现ref
(作为ByRef
),与CLR的支持相匹配。
回答
关于ref vs. out的另一条注释:两者之间的区别由Ccompiler强制执行。 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) {}