【问题标题】:<arrayname>.Contains method always returns false<arrayname>.Contains 方法总是返回 false
【发布时间】:2020-04-19 17:26:14
【问题描述】:

随机生成扑克牌的类:

class Card
{
    private string face;
    private string suit;

    //Constructor
    public Card()
    {
        string[] faceArray = {"Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight"
        , "Nine", "Ten", "Jack", "Queen", "King"};
        string[] suitArray = { "Clubs", "Hearts", "Spades", "Diamonds" };

        Random rand = new Random();
        face = faceArray[rand.Next(0, 13)];
        Thread.Sleep(150);
        Random dand = new Random();
        suit = suitArray[dand.Next(0, 4)];
    }
    //Method face of suit
    public override string ToString()
    {
        return face + " of " + suit;
    }
}

我认为这可以正常工作,但问题出在:

class DeckOfCards
{
    private Card[] deck = new Card[52];

    //constructor fills deck with unique cards
    public DeckOfCards()
    {
        for (int i = 0; i < 52; i++)
        {
            Card tempCard = new Card();
            if (deck.Contains(tempCard))
                 i--; 
            else               
                 deck[i] = tempCard; 
        }
    }
}

即使我有:

if (deck.Contains(tempCard))
                     i--; 

套牌仍然产生重复。我是不是用错了数组方法?

【问题讨论】:

  • 你创建了一张新的临时卡,然后检查卡组是否包含它,为什么会返回 true?
  • 临时卡有面值和花色值。我的目的是检查数组是否包含具有相同属性的卡。我不确定我是否正确使用它
  • 那么你应该检查属性的值,而不是对象。不要使用 contains 方法。
  • 我不知道该怎么做。我将如何比较对象的值?
  • 对不起,我不太清楚你所说的“包含功能”是什么意思。 .Contains 已经在 Visual Studios 的 c# 中

标签: c# arrays class


【解决方案1】:

您正在尝试检查 Card 对象。 因此它将使用该类的 .Equals() 方法。

请用您的业务逻辑覆盖 Card 类的 Equals() 方法。 然后它将按您的预期工作。

class Card
{
    private string face;
    private string suit;

    //
    // your other methods
    //

    public override bool Equals(object obj)
    {
        var item = obj as Card;

        if (item == null)
        {
           return false;
        }

        return this.face.Equals(item.face) && this.suit.Equals(item.suit);
    }
}

【讨论】:

  • 我会用 .Equals() 替换 .Contains() 吗?
  • 没有。在 Card 类中添加 Equals() 方法。不要更改其他代码。
【解决方案2】:

实际上,您在数组上没有 Contains 方法,但例如在 List 上有它。所以你的实际代码不应该编译。但是,我们可以保留数组并使用方法扩展,而不是使用 List。方法扩展是一种很酷的方法,可以使用未定义但在特定上下文中可能有用的方法来扩展类。所以让我们在纸牌上添加一个 Contains 方法。

我们可以这样做:

public static class CardFinder
    {
        public static bool Contains(this Card[] deck, Card card)
        {
            if (deck == null)
                return false;

            Card c = Array.Find(deck, c => c != null && c.face.Equals(card.face) && c.suit.Equals(card.suit));

            return c != null;
        }
    }

这里的语法很特殊。首先类应该是静态的,我们可以注意到在Card[] 类型的第一个参数之前关键字 this 的存在。这就是告诉框架我们想要使用我们当前定义的名为 Contains 的新方法扩展 Card[] 类型的方法。

在我们使用Array.Find方法的方法中,我们在MSDN中定义如下

搜索与指定谓词定义的条件匹配的元素,并返回整个 Array 中的第一个匹配项。

为了比较,我们还需要使 Card 的字段可访问,所以让我们更改它们的可见性并为它们定义 gettersetter。 Card 类的开头如下所示(其余部分保持不变)

public class Card
{
     public string face { get; set; }
     public string suit { get; set; }

     // Rest of code here ...
}

DeckOfCards 类也不需要更改,但为了打印商品,我重写了它的 ToString 方法,如下所示:

public override string ToString()
{
   StringBuilder builder = new StringBuilder();
   foreach (var card in deck)
      builder.Append(card.ToString() + "\n");
   return builder.ToString();
}

不,我们可以测试并查看它是否按预期工作(计算需要一点时间,因此这里肯定有优化的机会,但我希望这会有所帮助):

【讨论】:

  • Linq 将支持数组使用 Contains() 方法。
猜你喜欢
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多