[英]Why ref and out in C#?
使用關鍵字ref
,調用代碼需要初始化傳遞的參數,但是使用關鍵字out
我們不需要這樣做。
out
到處都用? ref
並且不能使用的out
? 答案在這篇MSDN文章中給出。 從那篇文章:
由
out
和ref
尋址的兩個參數傳遞模式略有不同,但它們都非常常見。 這些模式之間的細微差別導致一些非常常見的編程錯誤。 這些包括:
- 不為所有控制流路徑中的
out
參數賦值- 不將值賦給用作
ref
參數的變量因為C#語言為這些不同的參數傳遞模式分配了不同的明確賦值規則,所以這些常見的編碼錯誤被編譯器捕獲為不正確的C#代碼。
決定包括
ref
和out
參數傳遞模式的關鍵是允許編譯器檢測這些常見的編碼錯誤值得在語言中同時具有ref
和out
參數傳遞模式的額外復雜性。
out
是一種特殊形式的ref
,其中引用的內存不應在調用之前初始化。
在這種情況下,C#編譯器強制在方法返回之前分配out
變量,並且在分配變量之前不使用該變量。
兩個例子,其中out
不工作,但ref
的作用:
void NoOp(out int value) // value must be assigned before method returns
{
}
void Increment(out int value) // value cannot be used before it has been assigned
{
value = value + 1;
}
這些答案都不能讓我滿意,所以這里是我采取的ref
對out
。
我的回答是以下兩頁的摘要:
相比
ref
/ out
關鍵字 out
或ref
傳遞,因為屬性確實是方法 ref
/ out
在編譯時不被視為方法簽名的一部分,因此如果方法之間的唯一區別是其中一個方法采用ref
參數而另一個方法采用out
參數,則方法不能重載 對比
ref
out
例子
不會編譯,因為只有方法簽名的差異是ref
/ out
:
public void Add(out int i) { }
public void Add(ref int i) { }
使用ref
關鍵字:
public void PrintNames(List<string> names)
{
int index = 0; // initialize first (#1)
foreach(string name in names)
{
IncrementIndex(ref index);
Console.WriteLine(index.ToString() + ". " + name);
}
}
public void IncrementIndex(ref int index)
{
index++; // initial value was passed in (#2)
}
使用out
關鍵字:
public void PrintNames(List<string> names)
{
foreach(string name in names)
{
int index; // not initialized (#1)
GetIndex(out index);
Console.WriteLine(index.ToString() + ". " + name);
}
}
public void GetIndex(out int index)
{
index = IndexHelper.GetLatestIndex(); // needs to be assigned a value (#2 & #3)
}
作者的隨機評論
out
關鍵字的概念類似於使用ParameterDirection的Output
枚舉值在ADO.NET中聲明輸出參數 ref
必須使用ref
關鍵字 例:
public void ReassignArray(ref int[] array)
{
array = new int[10]; // now the array in the calling code
// will point to this new object
}
有關引用類型與值類型的更多信息,請參閱傳遞引用類型參數(C#編程指南)
一個人為的例子,當你需要使用ref而不是out時,如下:
public void SquareThisNumber(ref int number)
{
number = number * number;
}
int number = 4;
SquareThisNumber(ref number);
這里我們希望number
是一個in-out變量,所以我們使用ref
。 如果我們用完out
,編譯器會給出一個錯誤,說我們在使用之前初始化了一個out
參數。
ref關鍵字允許您更改參數的值。 被調用的方法可以是調用鏈中的中間鏈接。 使用out關鍵字的方法只能在調用鏈的開頭使用。
另一個優點是現有值可以用在方法的邏輯中並且仍然保持返回值。
在Oracle函數中有明確的IN(默認和你沒有設置方向時得到的)IN / OUT和OUT參數。 等效是正常的(只是參數),ref [參數]和out [參數]。
編譯器知道在調用之前不應設置out變量。 這允許它們在使用前聲明。 但是它知道它必須在返回時使用的函數之前設置。
當我們在調用以out
關鍵字為前綴的方法時傳遞值時,它會將它視為完全不同,就像我們沒有將它傳遞給方法一樣。 相反,我們實際上是將out變量的值從方法的定義部分收集(outing)到我們調用該方法的method out變量參數。
因此out variable
是在方法定義中完成的處理輸出,這就是我們需要創建它,初始化它並僅在定義中修改它的原因。
當我們需要從特定方法返回多個值時,使用out
變量。
在ref
變量的情況下,我們需要首先初始化它,因為它的內存位置被轉換為方法定義作為參數。 想想如果我們在傳遞之前沒有初始化會發生什么?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.