我继承了一些代码,其中Equals被覆盖,但不是==。我解决了这个问题,但是发现了更多问题。在调用代码中,对象是使用接口构造的,然后进行比较,结果与预期不符。我在下面放了一个完整的最小示例。简而言之,给定ISilly i1 = new Silly()和ISilly i2 = new Silly,i1 == i2返回false,而不是true。有没有办法解决这个问题,我应该吗?我看到一些类似“ i1和i2是接口的论点。可能有很多类是从ISilly派生的,所以请问i1和i2是否仅在引用相等的意义上才有意义”。如果是的话,我的两个问题是:
我尝试放入公共静态布尔运算符==(ISilly s1,ISilly s2)-注意接口而不是类名。我收到编译器错误。
我在这里想念什么?我尝试搜索一篇没有运气的文章。我本以为这是一个普遍的问题。
[如果有任何不清楚的地方,请告诉我,否则我可以提供更多信息。谢谢,戴夫
更新!!!我刚刚发现了这个相关问题:Operator Overloading with Interface-Based Programming in C#在我阅读本文时,答案似乎表明您不能在接口中使用==,并且答案之一建议使用诸如Resharper之类的第三方工具来禁止使用它。考虑到它会产生什么讨厌的错误,我完全质疑==的用处。为什么甚至允许它?
namespace EqualityProblems
{
class Program
{
static void Main(string[] args)
{
// just use class, not interface!
Silly s1 = new Silly();
Silly s2 = new Silly();
Silly s3 = new Silly(42);
Silly s4 = null;
Silly s5 = null;
Console.WriteLine("s1.Equals(s2) should be true " + s1.Equals(s2)); // should be true
Console.WriteLine("s1.Equals(s3) should be false " + s1.Equals(s3)); // should be false
Console.WriteLine("s1.Equals(s4) should be false " + s1.Equals(s4)); // should be false
Console.WriteLine("s1 == s2 should be true " + (s1 == s2)); // should be true
Console.WriteLine("s1 != s2 should be false " + (s1 != s2)); // should be false
Console.WriteLine("s1 == s3 should be false " + (s1 == s3)); // should be false
Console.WriteLine("s4 == s1 should be false " + (s4 == s1)); // should be false
Console.WriteLine("s1 == s4 should be false " + (s1 == s4)); // should be false
Console.WriteLine("s4 == s5 should be true " + (s4 == s5)); // should be true;both are null
//Console.WriteLine("s4.Equals(s1) should crash " + s4.Equals(s1)); // should crash. s4 is null
ISilly i1 = new Silly();
ISilly i2 = new Silly();
ISilly i3 = new Silly(42);
ISilly i4 = null;
ISilly i5 = null;
Console.WriteLine("i1.Equals(i2) should be true " + i1.Equals(i2)); // should be true
Console.WriteLine("i1.Equals(i3) should be false " + i1.Equals(i3)); // should be false
Console.WriteLine("i1.Equals(i4) should be false " + i1.Equals(i4)); // should be false
Console.WriteLine("i1 == i2 should be true " + (i1 == i2)); // should be true BUT IS FALSE
Console.WriteLine("i1 != i2 should be false " + (i1 != i2)); // should be false BUT IS TRUE
Console.WriteLine("i1 == i3 should be false " + (i1 == i3)); // should be false
Console.WriteLine("i4 == i1 should be false " + (i4 == i1)); // should be false
Console.WriteLine("i1 == i4 should be false " + (i1 == i4)); // should be false
Console.WriteLine("i4 == i5 should be true " + (i4 == i5)); // should be true;both are null
//Console.WriteLine("i4.Equals(i1) should crash " + i4.Equals(i1)); // should crash. i4 is null
}
}
public interface ISilly
{
int Length { get; set; }
}
public class Silly : ISilly
{
public Silly(int n) { Length = n; }
public Silly() { Length = 7; }
public int Length { get; set; }
public override bool Equals(object obj)
{
return obj is ISilly sl && (sl.Length == Length);
}
public bool Equals(Silly other)
{
if (other == null) return false;
return Length == other.Length;
}
public override int GetHashCode()
{
return Length;
}
public static bool operator ==(Silly s1, Silly s2)
{
if (ReferenceEquals(s1, null))
{
return ReferenceEquals(s2, null) ? true : false;
}
return s1.Equals(s2);
}
public static bool operator !=(Silly fs1, Silly fs2)
{
return !fs1.Equals(fs2);
}
}
}
不知道是否有可能,但是如果您可以使用抽象类而不是接口,则可以将==运算符实现为对抽象Equals()的调用。
这样,在派生类上使用==的任何人都会得到与调用Equals相同的结果。