2009-12-13 70 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#你可能会发现有用的,除了这里的答案。