C# - 具有接口类型列表的相等运算符未按预期工作
C# - equality operator with list of interface type not working as expected
考虑以下代码,其中 ClassOne
是从 IClass
派生的 class:
List<IClass> list = new List<IClass>();
list.Add(new ClassOne("foo", "bar"));
list.Add(new ClassOne("baz", "bam"));
List<IClass> list2 = new List<IClass>();
list2.Add(new ClassOne("foo", "bar"));
list2.Add(new ClassOne("baz", "bam"));
if (list == list2)
Console.WriteLine("Lists are equal.");
else
Console.WriteLine("Lists are NOT equal.");
相等运算符 return 为假(即列表不匹配),除此之外 operator ==
、operator !=
、Equals(ClassOne)
、Equals(object)
和 GetHashCode()
已经 implemented/overridden ClassOne
。这是为什么?我希望相等运算符 return 为真。是否有任何其他 methods/interfaces 必须实施才能使 ==
运算符按预期工作?
作为参考,这里是 ClassOne
和 IClass
的实现:
public interface IClass
{
string getA();
string getB();
} //interface
public class ClassOne : IClass, IEquatable<ClassOne>
{
public ClassOne(string a, string b)
{
strA = a;
strB = b;
}
public string getA()
{
return strA;
}
public string getB()
{
return strB;
}
public bool Equals(ClassOne other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (!string.Equals(strA, other.strA))
return false;
return string.Equals(strB, other.strB);
}
public override bool Equals(object other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (other is ClassOne)
{
ClassOne c1 = (ClassOne)other;
return Equals(c1);
}
//not ClassOne, so it is not equal
return false;
}
public override int GetHashCode()
{
int hc_a = -1;
if (null != strA)
hc_a = strA.GetHashCode();
int hc_b = -1;
if (null != strB)
hc_b = strB.GetHashCode();
return hc_a ^ hc_b;
}
public static bool operator ==(ClassOne left, ClassOne right)
{
if (ReferenceEquals(left, right)) return true;
if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
return false;
return left.Equals(right);
}
public static bool operator !=(ClassOne left, ClassOne right)
{
return !(left == right);
}
private string strA, strB;
} //class
任何正确方向的帮助或提示都将不胜感激。谢谢。
Why is that? I would expect the equality operator to return true.
不正确 - ==
运算符(和 Equals()
)未在 List<T>
上定义以检查其内容的相等性 - 它默认引用定义在上的运算符的相等性object
。由于两个列表是不同的对象,==
returns false.
您可以使用 Linq SequenceEqual
方法来确定两个列表是否包含相同顺序的相同对象:
if (list.SequenceEqual(list2))
Console.WriteLine("Lists are equal.");
else
Console.WriteLine("Lists are NOT equal.");
因为 ==
运算符没有为 List<T>
class 重载。 ==
对于列表来说只是引用相等。即使两个 List<int>
持有相同 int
的对象也不相等,等等
如果你问是否list == list2
,编译器会为List<T>
调用==
运算符,而List<T>
class的设计者已经决定了只有当两个列表都引用同一个列表时,两个列表才相等。换句话说:
public class List<T> {
public static bool operator ==(List<T> left, List<T> right) {
return ReferenceEquals(left, right);
}
}
(可见List<T>
class的内容比较多,而且由于使用了引用相等,所以not要重载运算符) .
考虑以下代码,其中 ClassOne
是从 IClass
派生的 class:
List<IClass> list = new List<IClass>();
list.Add(new ClassOne("foo", "bar"));
list.Add(new ClassOne("baz", "bam"));
List<IClass> list2 = new List<IClass>();
list2.Add(new ClassOne("foo", "bar"));
list2.Add(new ClassOne("baz", "bam"));
if (list == list2)
Console.WriteLine("Lists are equal.");
else
Console.WriteLine("Lists are NOT equal.");
相等运算符 return 为假(即列表不匹配),除此之外 operator ==
、operator !=
、Equals(ClassOne)
、Equals(object)
和 GetHashCode()
已经 implemented/overridden ClassOne
。这是为什么?我希望相等运算符 return 为真。是否有任何其他 methods/interfaces 必须实施才能使 ==
运算符按预期工作?
作为参考,这里是 ClassOne
和 IClass
的实现:
public interface IClass
{
string getA();
string getB();
} //interface
public class ClassOne : IClass, IEquatable<ClassOne>
{
public ClassOne(string a, string b)
{
strA = a;
strB = b;
}
public string getA()
{
return strA;
}
public string getB()
{
return strB;
}
public bool Equals(ClassOne other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (!string.Equals(strA, other.strA))
return false;
return string.Equals(strB, other.strB);
}
public override bool Equals(object other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (other is ClassOne)
{
ClassOne c1 = (ClassOne)other;
return Equals(c1);
}
//not ClassOne, so it is not equal
return false;
}
public override int GetHashCode()
{
int hc_a = -1;
if (null != strA)
hc_a = strA.GetHashCode();
int hc_b = -1;
if (null != strB)
hc_b = strB.GetHashCode();
return hc_a ^ hc_b;
}
public static bool operator ==(ClassOne left, ClassOne right)
{
if (ReferenceEquals(left, right)) return true;
if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
return false;
return left.Equals(right);
}
public static bool operator !=(ClassOne left, ClassOne right)
{
return !(left == right);
}
private string strA, strB;
} //class
任何正确方向的帮助或提示都将不胜感激。谢谢。
Why is that? I would expect the equality operator to return true.
不正确 - ==
运算符(和 Equals()
)未在 List<T>
上定义以检查其内容的相等性 - 它默认引用定义在上的运算符的相等性object
。由于两个列表是不同的对象,==
returns false.
您可以使用 Linq SequenceEqual
方法来确定两个列表是否包含相同顺序的相同对象:
if (list.SequenceEqual(list2))
Console.WriteLine("Lists are equal.");
else
Console.WriteLine("Lists are NOT equal.");
因为 ==
运算符没有为 List<T>
class 重载。 ==
对于列表来说只是引用相等。即使两个 List<int>
持有相同 int
的对象也不相等,等等
如果你问是否list == list2
,编译器会为List<T>
调用==
运算符,而List<T>
class的设计者已经决定了只有当两个列表都引用同一个列表时,两个列表才相等。换句话说:
public class List<T> {
public static bool operator ==(List<T> left, List<T> right) {
return ReferenceEquals(left, right);
}
}
(可见List<T>
class的内容比较多,而且由于使用了引用相等,所以not要重载运算符) .