List.Contains对象比较失败

时间:2014-02-07 10:14:10

标签: c# .net list class object

我有一个类“Class1”,在.NET 2.0中有一个字符串变量“sText”。我创建了该类“lstClass1”的对象列表。它在设置字符串变量后存储该类的许多对象。

完整的代码是:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (!lstClass1.Contains(new Class1("text1")))
            lstClass1.Add(new Class1("text1"));
    }

    public List<Class1> lstClass1 = new List<Class1>();
}

public class Class1
{
    public Class1(string sText)
    {
        this.sText = sText;
    }

    public string sText = "";
}

现在,问题是我只想添加具有唯一文本值的字符串的类对象。例如,如果lstClass1已经有一个字符串变量值为“text1”的对象,那么它不应该允许添加一个也具有“text1”的对象。所以,我写了代码:

if (!lstClass1.Contains(new Class1("text1")))
    lstClass1.Add(new Class1("text1"));

但即使列表中已存在带有“text1”字符串的对象,它也始终允许添加文本“text1”。我的假设是,在第一个按钮单击事件“button1_Click”时,将添加该对象,因为列表为空但在下一个按钮上单击List.Contains函数将检查列表中是否已存在字符串变量“text1”并且如果找到则不会添加。但它总是允许添加带有文本“text1”的对象,即使它已经存在于列表中。

请注意:我没有采用简单的字符串列表或字符串,因为我想以简单的方式解释列表,类和对象的大问题。

请帮忙。

4 个答案:

答案 0 :(得分:8)

使用Any()方法:

if (!lstClass1.Any(x => x.sText == "text1"))
    lstClass1.Add(new Class1("text1"));

此代码:

if (!lstClass1.Contains(new Class1("text1")))
    lstClass1.Add(new Class1("text1"));

仅在您为Equals()提供GetHashCode()Class1方法才能在此类的两个对象之间进行比较时才有效。为实现此目的,您的类应实现IEquatable接口。 所以你的Class1看起来像这样:

public class Class1 : IEquatable<Class1>
{
    public Class1(string sText)
    {
        this.sText = sText;
    }

    public string sText = "";

    public bool Equals(Class1 other) 
    {
      if (other == null) 
         return false;

      if (this.sText == other.sText)
         return true;
      else
         return false;
    }

    public override int GetHashCode()
    {
      return this.sText.GetHashCode();
    }
}

答案 1 :(得分:1)

只有在你的情况下实现IEquatable时,包含才能正常工作。

您可以改用以下代码:

public class Class1 //: IEquatable<Class1>
{
    public string sText = "";
    public Class1(string sText)
    {
        this.sText = sText;
    }

    //public bool Equals(Class1 other)
    //{
    //    return this.sText == other.sText;
    //}
}
static void Main(string[] args)
{
    List<Class1> lstClass1 = new List<Class1>() { new Class1("text1") };
    if (!lstClass1.Contains(new Class1("text1")))
        lstClass1.Add(new Class1("text1"));
    Console.WriteLine(lstClass1.Count);
    Console.ReadKey();
}

取消注释评论的行,您将看到差异。

答案 2 :(得分:0)

这会失败,因为列表会在您的实例上调用Equals,并且默认实现会检查引用相等性。虽然您的对象具有name属性值,但它是一个差异实例,因此引用将不相等。

Class1中覆盖Equals方法以比较基础属性

public override bool Equals(object other)
{
  Class1 rhs=other as Class1;
  if(rhs==null) return false;

  return this.sText == rhs.sText;
}

答案 3 :(得分:0)

您在这里面临的问题是在对象和实例之间。当您检查以下内容时,您基本上是在询问“是否在集合中?”

!lstClass1.Contains(new Class1("text1"))

嗯,显然不可能因为你刚刚创建了它。您需要检查的是该对象的内容。最简单的方法是迭代整个集合并检查每个对象的内容。

使用LINQ非常容易(虽然我不确定它是否适用于.NET 2.0):

!lstClass1.Any(i => i.Text == "text1")

另一种解决方案是覆盖Class1的GetHashCode()Equals方法,如果它们的内容相同,则将两个对象视为“等于”。因此可以进行彻底的比较。