退出
ref
和 out
关键字导致参数通过引用传递,而不是通过值传递。对于值类型,这意味着被调用者可以更改变量的值。
int x = 5;
ChangeX(ref x);
// The value of x could be different now
对于引用类型,变量中的实例不仅可以修改(没有 ref
的情况),但它也可以完全替换:
Address a = new Address();
ChangeFieldInAddress(a);
// a will be the same instance as before, even if it is modified
CreateANewInstance(ref a);
// a could be an entirely new instance now
out
和 ref
关键字之间的主要区别在于 ref
要求变量由调用者初始化,而 out
将该责任传递给被调用者。
要使用 out
参数,方法定义和调用方法都必须明确使用 out
关键字。
int number = 1;
Console.WriteLine("Before AddByRef: " + number); // number = 1
AddOneByRef(ref number);
Console.WriteLine("After AddByRef: " + number); // number = 2
SetByOut(out number);
Console.WriteLine("After SetByOut: " + number); // 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
//if we have an interface like this
interface ICovariant<out R> { }
//and two variables like
ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();
// then the following statement is valid
// without the out keyword this would have thrown error
iobj = istr; // implicit conversion occurs here