退出
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