【问题标题】:Updating one instance of a class causes another to update更新一个类的实例会导致另一个更新
【发布时间】:2018-02-02 21:59:38
【问题描述】:

我正在编写一个模拟洗牌和抽牌的基本程序。抽完之后,我在牌组数组中为牌组的类变量赋予了 0 和 null 的值,分别代表等级和花色,以检查牌是否是从牌组中抽出的。但是,当我将卡片组数组中的卡片设置为 0 和 null 时,它也会将手数组中的卡片设置为相同。任何解决问题的建议都非常感谢。谢谢!

抽卡按钮代码:

Card drawn = new Card(0, null);
        //
        do
        {
            i++;
            drawn = test.cards[i];
        } while (drawn.rank == 0 || drawn.suit == null);
        //
        output = drawn.rank + " " + drawn.suit;
        lblOutput.Text = output;
        //
        addToHand(drawn);
        if (handCount < 5)
        {
            handCount++;
        }
        test.cards[i].suit = null;
        test.cards[i].rank = 0;
        //
        if (i >= 51)
        {
            MessageBox.Show("You have drawn all the cards.");
            btnDraw.Enabled = false;
            btnShuffle.Enabled = false;
        }

addToHand 函数:

private void addToHand(Card drawn)
    {
        if (handCount < 5)
        {
                if (hand[0].suit == null)
                {
                    hand[0] = drawn;
                    button1.Text = hand[0].rank + " " + hand[0].suit;
                    button1.Enabled = true;
                }
                else if (hand[1].suit == null)
                {
                    hand[1] = drawn;
                    button2.Text = hand[1].rank + " " + hand[1].suit;
                    button2.Enabled = true;
                }
                else if (hand[2].suit == null)
                {
                    hand[2] = drawn;
                    button3.Text = hand[2].rank + " " + hand[2].suit;
                    button3.Enabled = true;
                }
                else if (hand[3].suit == null)
                {
                    hand[3] = drawn;
                    button4.Text = hand[3].rank + " " + hand[3].suit;
                    button4.Enabled = true;
                }
                else if (hand[4].suit == null)
                {
                    hand[4] = drawn;
                    button5.Text = hand[4].rank + " " + hand[4].suit;
                    button5.Enabled = true;
                }
        }

这里是甲板和卡片的类:

public class Deck
{
    public Card[] cards;

    public Deck() //Fills new array with 52 cards
    {
        cards = new Card[52];
        var index = 0;

        foreach (var suit in new[] { "Spades", "Hearts", "Clubs", "Diamonds", })
        {
            for (var rank = 1; rank <= 13; rank++)
            {
                cards[index++] = new Card(rank, suit);
            }
        }
    }
}

public class Card
{
    public int rank { get; set; }
    public string suit { get; set; }

    public Card(int rk, string st)
    {
        rank = rk;
        suit = st;
    }
}

【问题讨论】:

  • 这是引用类型的基础知识。不要将test.cards[i].suit 分配给null,而是将整个卡test.cards[i] 设置为null

标签: c# visual-studio


【解决方案1】:

C# 对象本质上是按引用传递的,而不是按值传递的。所以当你这样做时:

Card card = cards[0];

您不是在创建新卡,而是在引用已创建的卡。因此,当您更改 card[0] 的值时,对该值的每个引用都会更改。

您可能想要“克隆”它,或者在您的情况下,只需复制卡内的所有数据。

Card card = new Card();
card.suit = cards[0].suit;
card.rank = cards[0].rank;

任何不是值类型的东西都需要以同样的方式克隆。

【讨论】:

  • “原始类型,例如 int 和 string,是按值传递的”,这是错误的。不是原语,只有作为值类型的原语。您还可以创建任何 struct,其行为方式与 int 完全相同
  • 感谢您的解释!
【解决方案2】:

当你写hand[0] = drawn;hand[0] 和draw 是同一个对象。 如果您想拥有相同的值但在两个不同的对象中,您可以:

  • 使用复制构造函数:new Hand(drawn)
  • 使用绘制对象的Clone方法(实现ICloneable)。

您可能会对 IClonneable 界面感兴趣:

https://msdn.microsoft.com/en-us/library/system.icloneable.clone(v=vs.110).aspx

还有复制构造函数:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-write-a-copy-constructor

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    • 1970-01-01
    • 2020-07-18
    • 2021-10-30
    • 2017-09-05
    • 1970-01-01
    • 2016-08-25
    相关资源
    最近更新 更多