ref和out关键字导致参数按引用传递,而不是按值传递。对于值类型,这意味着被调用方可以更改变量的值。
int x = 5; ChangeX(ref x); // x的值现在可能会不同
对于引用类型,变量中的实例不仅可以被修改(如没有的情况一样ref),还可以被完全替换:
Address a = new Address(); ChangeFieldInAddress(a); // 即使已修改,a也将与以前相同 CreateANewInstance(ref a); // 现在可能是一个全新的实例
out和ref关键字之间的主要区别在于,它ref要求变量由调用方初始化,同时out将责任传递给被调用方。
要使用out参数,方法定义和调用方法都必须显式使用out关键字。
int number = 1; Console.WriteLine("在AddByRef之前: " + number); // 数= 1 AddOneByRef(ref number); Console.WriteLine("在AddByRef之后: " + number); // 数= 2 SetByOut(out number); Console.WriteLine("在SetByOut之后: " + number); // 数= 34 void AddOneByRef(ref int value) { value++; } void SetByOut(out int value) { value = 34; }
以下就不能编译,因为out参数必须在方法返回之前分配(它会编译使用的值ref代替):
void PrintByOut(out int value) { Console.WriteLine("Hello!"); }
使用out关键字作为通用修饰符
out定义通用接口和委托时,也可以在通用类型参数中使用关键字。在这种情况下,out关键字指定type参数是协变的。
通过协方差,您可以使用比通用参数指定的类型更多的派生类型。这允许实现变体接口的类的隐式转换和委托类型的隐式转换。引用类型支持协方差和协方差,但值类型不支持它们。-MSDN
//如果我们有这样的界面 interface ICovariant<out R> { } //和两个变量 ICovariant<Object> iobj = new Sample<Object>(); ICovariant<String> istr = new Sample<String>(); // 那么以下语句是有效的 // 没有out关键字,这将引发错误 iobj = istr; // 隐式转换在这里发生