List.Contains对象比较失败

我有一个类“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 lstClass1 = new List(); } 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”的对象,即使它已经存在于列表中。

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

请帮忙。

使用Any()方法:

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

这段代码:

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

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

 public class Class1 : IEquatable { 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(); } } 

只有在您的情况下实现IEquatable时,Contains才能正常工作。

您可以使用以下代码:

 public class Class1 //: IEquatable { 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 lstClass1 = new List() { new Class1("text1") }; if (!lstClass1.Contains(new Class1("text1"))) lstClass1.Add(new Class1("text1")); Console.WriteLine(lstClass1.Count); Console.ReadKey(); } 

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

这会失败,因为列表会在您的实例上调用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; } 

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

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

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

LINQ很容易做到这一点(虽然我不确定它是否适用于.NET 2.0):

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

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