C#参考之方法参数关键字:params、ref及out
params
使用 params 关键字可以指定采用数目可变的参数的方法参数。
可以发送参数声明中所指定类型的逗号分隔的参数列表或指定类型的参数数组。 还可以不发送参数。 如果未发送任何参数,则 params 列表的长度为零。
在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字。
1 public class MyClass 2 { 3 public static void UseParams(params int[] list) 4 { 5 for (int i = 0; i < list.Length; i++) 6 { 7 Console.Write(list[i] + " "); 8 } 9 Console.WriteLine(); 10 } 11 12 public static void UseParams2(params object[] list) 13 { 14 for (int i = 0; i < list.Length; i++) 15 { 16 Console.Write(list[i] + " "); 17 } 18 Console.WriteLine(); 19 } 20 21 static void Main() 22 { 23 // You can send a comma-separated list of arguments of the 24 // specified type. 25 UseParams(1, 2, 3, 4); 26 UseParams2(1, 'a', "test"); 27 28 // A params parameter accepts zero or more arguments. 29 // The following calling statement displays only a blank line. 30 UseParams2(); 31 32 // An array argument can be passed, as long as the array 33 // type matches the parameter type of the method being called. 34 int[] myIntArray = { 5, 6, 7, 8, 9 }; 35 UseParams(myIntArray); 36 37 object[] myObjArray = { 2, 'b', "test", "again" }; 38 UseParams2(myObjArray); 39 40 // The following call causes a compiler error because the object 41 // array cannot be converted into an integer array. 42 //UseParams(myObjArray); 43 44 // The following call does not cause an error, but the entire 45 // integer array becomes the first element of the params array. 46 UseParams2(myIntArray); 47 } 48 } 49 /* 50 Output: 51 1 2 3 4 52 1 a test 53 54 5 6 7 8 9 55 2 b test again 56 System.Int32[] 57 */
ref
ref 关键字会导致参数通过引用传递,而不是通过值传递。 通过引用传递的效果是,对所调用方法中的参数进行的任何更改都反映在调用方法中。 例如,如果调用方传递本地变量表达式或数组元素访问表达式,所调用方法会将对象替换为 ref 参数引用的对象,然后调用方的本地变量或数组元素将开始引用新对象。
注意:不要混淆通过引用传递的概念与引用类型的概念。 这两种概念是不同的。 无论方法参数是值类型还是引用类型,均可由 ref 修改。 当通过引用传递时,不会对值类型装箱。
若要使用 ref 参数,方法定义和调用方法均必须显式使用 ref 关键字,如下面的示例所示。
1 class RefExample 2 { 3 static void Method(ref int i) 4 { 5 // Rest the mouse pointer over i to verify that it is an int. 6 // The following statement would cause a compiler error if i 7 // were boxed as an object. 8 i = i + 44; 9 } 10 11 static void Main() 12 { 13 int val = 1; 14 Method(ref val); 15 Console.WriteLine(val); 16 17 // Output: 45 18 } 19 }
out
可以在两个上下文(每个都是指向详细信息的链接)中使用 out 上下文关键字作为参数修饰符,或在接口和委托中使用泛型类型参数声明。
如果希望方法返回多个值,可以声明 out 方法。下面的示例使用 out 返回具有单个方法调用的三个变量。注意,第三个参数赋 null 值。这使得方法可以有选择地返回值。
1 class OutReturnExample 2 { 3 static void Method(out int i, out string s1, out string s2) 4 { 5 i = 44; 6 s1 = "I've been returned"; 7 s2 = null; 8 } 9 static void Main() 10 { 11 int value; 12 string str1, str2; 13 Method(out value, out str1, out str2); 14 // value is now 44 15 // str1 is now "I've been returned" 16 // str2 is (still) null; 17 } 18 }
注意:传递到 ref 形参的实参必须先经过初始化,然后才能传递。 这与 out 形参不同,在传递之前,不需要显式初始化该形参的实参。 尽管作为 out 参数传递的变量无需在传递之前初始化,调用方法仍要求在方法返回之前赋值。
类的成员不能具有仅在 ref 和 out 方面不同的签名。 如果类型的两个成员之间的唯一区别在于其中一个具有 ref 参数,而另一个具有 out 参数,则会发生编译错误。 例如,以下代码将不会编译。
1 class CS0663_Example 2 { 3 // Compiler error CS0663: "Cannot define overloaded 4 // methods that differ only on ref and out". 5 public void SampleMethod(out int i) { } 6 public void SampleMethod(ref int i) { } 7 }
但是,当一个方法具有 ref 或 out 参数,另一个方法具有值参数时,则可以完成重载,如下面的示例所示。
1 class RefOverloadExample 2 { 3 public void SampleMethod(int i) { } 4 public void SampleMethod(ref int i) { } 5 }
在其他要求签名匹配的情况下(如隐藏或重写),ref 和 out 是签名的一部分,相互之间不匹配。
属性不是变量。 它们是方法,不能传递到 ref 参数。
不能将 ref 和 out 关键字用于以下几种方法:
异步方法,通过使用 async 修饰符定义。
迭代器方法,包括 yield return 或 yield break 语句。
本文来自博客园,作者:Arthurian,转载请注明原文链接:https://www.cnblogs.com/Arthurian/p/5761863.html
欢迎邮件交流:zhuanxinxin@aliyun.com