2012-03-26 79 views
8

我有兩種方法:C#傳引用類型VS out參數

public void A(List<int> nums) 
{ 
    nums.Add(10); 
} 

public void B(out List<int> nums) 
{ 
    nums.Add(10); 
} 

是這兩個調用之間的區別?

List<int> numsA = new List<int>(); 
A(numsA); 

List<int> numsB = new List<int>(); 
B(out numsB); 

一般來說,我想了解通過引用類型之間的區別,或者作爲輸出參數。

回答

6

在你的榜樣,方法B將無法​​編譯,因爲out參數被認爲是未初始化的,所以你必須初始化它,然後才能使用它。此外,調用方法與out參數時,需要指定在調用點的out關鍵字:

B(out numsB); 

而且你不需要調用之前初始化numbsB變量,因爲它會被覆蓋通過該方法。

喬恩斯基特有一個偉大的文章,解釋了各種方式來傳遞參數:Parameter passing in C#

0

版本B的,功能有變量直接訪問。它就像'ref'關鍵字一樣,除了變量必須從獲取參數的函數中分配。它可以讓你從一個函數返回多個值。調用語法是'B(out numsB);'

3

非參考非輸出參數(如局部變量)表示存儲位置。如果存儲位置的類型是引用類型,則存儲位置將持有對該類型實例的引用。

Ref和輸出參數,相反,保持的存儲位置的參考。該存儲位置可以是局部變量,字段或數組元素。換句話說,ref和out參數引入了另一個間接層。如果在方法中有引用類型的ref或out參數,那麼它表示對對象引用的引用。

爲什麼要引用對象的引用?如果您需要修改對象的引用(而不是修改對象本身)。

在一些狹隘的環境下,這是一種有用的技巧。例如,您可能要編寫訂單兩個隊列取決於其頂部有較小值的函數:如果你想從一個方法返回多個值

void OrderQueues(ref Queue<int> a, ref Queue<int> b) 
{ 
    if (a.Peek <= b.Peek) return; 
    var temp = a; 
    a = b; 
    b = temp; 
} 

輸出參數是有用的:

void OldestAndYoungest(IEnumerable<Person> people, out Person youngest, out Person oldest) 
{ 
    youngest = null; 
    oldest = null; 
    foreach (var person in people) 
    { 
     if (youngest == null || person.Age < youngest.Age) 
      youngest = person; 
     if (oldest == null || oldest.Age < person.Age) 
      oldest = person; 
    } 
} 

根據我的經驗,ref和out參數相當少見,甚至更少見於參考類型。

請注意,ref參數必須由調用方初始化,而out參數必須由被調用方初始化。如果您從不爲ref參數賦值,那麼它可能應該是一個「正常」參數。如果您從不向out參數賦值(如您的示例中所示),那麼您的代碼將無法編譯。