我有一个类“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”的对象,即使它已经存在于列表中。
请注意:我没有采用简单的字符串列表或字符串,因为我想以简单的方式解释列表,类和对象的大问题。
请帮忙。
答案 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
方法,如果它们的内容相同,则将两个对象视为“等于”。因此可以进行彻底的比较。