2009-12-13 104 views
2

爲什麼在下面更改卡片?讓我感到困惑..明白通過裁判哪些工作正常..但傳遞陣列是不符合我的期望。下.NET3.5SP1C#調用方法和變量範圍

非常感謝

void btnCalculate_Click(object sender, EventArgs e) 
{ 
    string[] cards = new string[3]; 
    cards[0] = "old0"; 
    cards[1] = "old1"; 
    cards[2] = "old2"; 
    int betResult = 5; 
    int position = 5; 
    clsRules myRules = new clsRules(); 
    myRules.DealHand(cards, betResult, ref position); // why is this changing cards! 
    for (int i = 0; i < 3; i++) 
     textBox1.Text += cards[i] + "\r\n"; // these are all new[i] .. not expected! 

    textBox1.Text += "betresult " + betResult.ToString() + "\r\n"; // this is 5 as expected 
    textBox1.Text += "position " + position.ToString() + "\r\n"; // this is 6 as expected 
} 

public class clsRules 
{ 
    public void DealHand(string[] cardsInternal, int betResultInternal, ref int position1Internal) 
    { 
     cardsInternal[0] = "new0"; 
     cardsInternal[1] = "new1"; 
     cardsInternal[2] = "new2"; 

     betResultInternal = 6; 
     position1Internal = 6; 
    } 
} 
+0

nzscott here aka Dave。謝謝大家。我發現http://rapidapplicationdevelopment.blogspot.com/2007/01/parameter-passing-in-c.html文章非常出色。 – 2009-12-14 10:54:55

回答

5

數組是指引用類型,簡而言之,數組的值不是直接包含在變量中。相反,變量指的是這個值。希望下面的代碼能夠更好地解釋這一點(List<T>也是一個引用類型)。

List<int> first = new List<int>()(new int[] {1,2,3}); 
List<int> second = first; 
first.Clear(); 
Console.WriteLine(second.Count); // Prints 0 

在這種情況下有在其上通過可變第一稱爲第一行創建的List<int>。第二行不會創建新列表,而是會創建第二個名爲second的變量,它將第一個變量指向同一List<int>對象。該邏輯適用於所有參考類型。

當您將可變卡片傳入方法時,您不會傳遞完整陣列的副本,而是傳遞可變卡片的副本。該副本引用與原始卡相同的數組對象。因此,對數組進行的任何修改都可以通過原始引用進行查看。

+0

第一行上的錯字,第一個大括號應該是圓形的: 列表 first = new List ()(new int [] {1,2,3}); – 2009-12-14 09:53:46

1

編譯當你傳遞一個數組,因爲它是不可複製的對象。接收方法使用同一個實例。 在某種意義上,數組總是被ref傳遞。 當一個數組以及任何其他引用類型的實例作爲參數傳遞時,receive方法將在同一個類型實例上獲取其自己的引用副本。沒有創建實際對象的副本。

如果您需要傳遞一份副本,則必須明確說明這一點:自己創建一個副本或克隆該陣列。它不爲你做的原因是顯而易見的 - 複製數組可以是昂貴的,你不想要它,除非確有必要

+0

說「在某種意義上數組總是被ref傳遞」並不是一個好主意,因爲忽略了引用通過的更嚴格的想法的真正含義。特別是,使其成爲ref參數*可以*改變行爲。 – 2009-12-13 16:56:48

4

引用類型的變量不 不直接包含其數據;它 包含對其數據的引用。當 您通過 值傳遞參考類型參數時,可以將引用指向的 數據更改爲類成員的值,例如 。 但是,您不能更改引用本身的值 ;也就是你 不能使用相同的引用來爲 分配一個新類的內存,並且 將它保留在該塊之外。至 這樣做,請使用 ref或out關鍵字傳遞參數。

http://msdn.microsoft.com/en-us/library/s6938f28(VS.80).aspx

2

你逝去引用類型(如陣列)的方法通過值,要傳遞一個拷貝的它的參考。它仍然是被引用的對象,它不會創建數組本身的副本。

1

數組是參考類型,因此可能會發生變化。

2

當將參數傳遞到方法,有三個不同的概念需要注意的:

  • 通過值Vs根據編碼參數
  • 值Vs引用類型
  • 易變VS不變類型

在你的例子中,字符串數組是一個引用類型,是一個可變類型,並通過值傳遞。編譯器總是讓你改變數組的內容,因爲它是可變的。但是,由於它是引用類型,因此調用代碼和被調用代碼都指向相同的數組內容,因此調用代碼「會看到更改」。在這種情況下,由傳遞的事實是無關緊要的,因爲儘管調用代碼的數組變量確實已經傳遞了調用代碼變量的副本,但它們都指向內存中的相同位置。

2

正如其他答案所說,這是因爲參考正在通過價值

我有一個article on argument passing in C#你可能會發現有用的,除了這裏的答案。