ref,val和out对方法参数意味着什么?

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

理想情况下,作为实际答案,虽然欢迎链接到良好的解释。

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

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

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

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

除了一个细微的差别外, 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没有相应的out和实现ref (仅作为ByRef ),匹配CLR的支持。

关于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) {} 

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

基本上它归结为:

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

但这确实是你能给出的最基本的答案,因为它比这里说的要复杂得多