为什么不';t列表.包含我所期望的工作
本文关键字:期望 工作 包含我 列表 为什么不 | 更新日期: 2023-09-27 18:27:08
为什么这个程序打印"未添加",而我认为它应该打印"添加"?
using System;
using System.Collections.Generic;
class Element
{
public int id;
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
Element ret = new Element(d);
return ret;
}
public static bool operator ==(Element e1, Element e2)
{
return (e1.id == e2.id);
}
public static bool operator !=(Element e1, Element e2)
{
return !(e1.id == e2.id);
}
}
class MainClass
{
public static void Main(string[] args)
{
List<Element> element = new List<Element>();
element.Add(2);
if(element.Contains(2))
Console.WriteLine("added");
else
Console.WriteLine("not added");
}
}
Contains
方法不使用==
运算符.问题出在哪里?
Contains方法不使用==运算符
否-它使用Equals
,您尚未覆盖它。。。因此,您得到了Equals
的默认行为,即检查引用标识。您应该重写Equals(object)
和GetHashCode
以使它们彼此一致——为了理智起见,也要与您的==
重载保持一致。
我还建议实现IEquatable<Element>
,List<Element>
将优先使用Equals(object)
,因为EqualityComparer<T>.Default
会适当地选择它。
哦,您的运算符重载也应该处理空引用。
我还强烈建议使用私有字段而不是公共字段,并使您的类型不可变-密封它并使id
只读。为可变类型实现相等可能会导致奇怪的情况。例如:
Dictionary<Element, string> dictionary = new Dictionary<Element, string>();
Element x = new Element(10);
dictionary[x] = "foo";
x.id = 100;
Console.WriteLine(dictionary[x]); // No such element!
之所以会发生这种情况,是因为哈希代码会发生变化(至少在大多数实现中是这样),因此字典下面的哈希表甚至无法找到对已经存在的相同对象的引用。
所以你的课看起来像这样:
internal sealed class Element : IEquatable<Element>
{
private readonly int id;
public int Id { get { return id; } }
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
return new Element(d);
}
public static bool operator ==(Element e1, Element e2)
{
if (object.ReferenceEquals(e1, e2))
{
return true;
}
if (object.ReferenceEquals(e1, null) ||
object.ReferenceEquals(e2, null))
{
return false;
}
return e1.id == e2.id;
}
public static bool operator !=(Element e1, Element e2)
{
// Delegate...
return !(e1 == e2);
}
public bool Equals(Element other)
{
return this == other;
}
public override int GetHashCode()
{
return id;
}
public override bool Equals(object obj)
{
// Delegate...
return Equals(obj as Element);
}
}
(顺便说一句,我不确定隐式转换的优点——我自己通常会远离这些。)
Contains方法不使用==运算符.问题出在哪里?
这是正确的。
此方法[Contains]通过使用默认的相等比较器来确定相等,该比较器由T(列表中值的类型)的IEquatable.Equals方法的对象实现定义。
http://msdn.microsoft.com/en-us/library/bhkz42b3(v=vs.110).aspx
您还需要重写Equals()。请注意,当您重载Equals()时,也重写GetHashCode()几乎总是正确的。
覆盖Equals
和GetHashCode
,如:
class Element
{
public int id;
protected bool Equals(Element other)
{
return id == other.id;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Element) obj);
}
public override int GetHashCode()
{
return id; //or id.GetHashCode();
}
//..... rest of the class
参见:List<T>.Contains Method
此方法通过使用默认相等来确定相等比较器,由对象的T(列表中值的类型)的
IEquatable<T>.Equals
方法。