C#调用方法和变量范围

时间:2009-12-13 15:50:24

标签: c#

为什么卡片会在下方更改?让我感到困惑..理解通过ref传递哪个工作正常..但是当传递数组时并没有像我预期的那样做。在.NET3.5SP1下编译

非常感谢

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;
    }
}

7 个答案:

答案 0 :(得分: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>对象。此逻辑适用于所有引用类型。

当您将变量卡传递给方法时,您不会传递完整数组的副本,而是传递变量卡的副本。此副本引用与原始卡相同的阵列对象。因此,通过原始引用可以看到对数组所做的任何修改。

答案 1 :(得分:4)

  

引用类型的变量   不直接包含其数据;它   包含对其数据的引用。什么时候   你通过引用类型参数传递   价值,有可能改变   这样的参考指出的数据   作为类成员的价值。   但是,您无法更改该值   引用本身;那是你   不能使用相同的参考   为新类分配内存   让它坚持在街区之外。至   这样做,使用传递参数   引用或退出关键字。

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

答案 2 :(得分:2)

当您通过值将引用类型(如数组)传递给方法时,您将传递它的引用的副本。它仍然是引用的同一个对象,它不会创建数组本身的副本。

答案 3 :(得分:2)

将参数传递给方法时,需要注意三个不同的概念:

  • 按价值与参考参数
  • 价值与参考类型
  • Mutable vs Immutable类型

在您的示例中,字符串数组是Reference类型,是Mutable类型,并按值传递。编译器将始终允许您更改数组的内容,因为它是Mutable。但是,由于它是Reference类型,因此调用代码和被调用代码都指向相同的数组内容,因此调用代码“看到了更改”。它在这种情况下通过值传递的事实是无关紧要的,因为虽然调用代码的数组变量确实已经传递了调用代码变量的副本,但它们都指向内存中的相同位置。 / p>

答案 4 :(得分:2)

正如其他答案所说,这是因为引用正在按值传递

除了这里的答案之外,我还有一个你会发现有用的article on argument passing in C#

答案 5 :(得分:1)

将数组作为对象传递时,不会复制它。接收方法使用相同的实例。 在某种意义上,数组总是通过ref传递。当一个数组以及任何其他引用类型的实例作为参数传递时,接收方法在同一个实例上获取它自己的引用副本类型。没有创建实际对象的副本。

如果您需要传递副本,则必须明确说明:自己创建副本或克隆数组。没有为你做的原因很明显 - 复制一个数组可能很昂贵,你不需要它,除非它真的是必要的

答案 6 :(得分:1)

数组是引用类型,因此可能会发生变化。