当 class 从接口派生时,C# 重写运算符 ==。我可以在接口中使用 == 还是如何防止它

C# Overriding operator == when class derives from interface. Can I use == with interface or how to prevent it

我继承了一些代码,其中 Equals 被覆盖但没有 ==。我解决了这个问题,但我发现了更多问题。在调用代码中,对象是使用接口构造的,然后进行比较,结果不是人们所期望的。我在下面放了一个完整的最小示例。 简而言之,给定 ISilly i1 = new Silly() 和 ISilly i2 = new Silly,i1==i2 return 为假,不为真。有没有办法解决这个问题,我应该这样做吗?我看到了一些类似 "i1 and i2 are interaces. There could be many classes that derive from ISilly so asking if i1 and i2 doesn't make sense except in a reference equality sense" 的论点。如果这是答案,我的两个问题是:

  1. 为什么 Equals 工作得这么漂亮?
  2. 如何阻止应用程序程序员调用 "i1 == i2"? him/her 比 i1.Equals(i2).
  3. 更自然

我尝试输入 public static bool operator ==(ISilly s1, ISilly s2)- 注意接口而不是 class 名称。我收到编译器错误。

我在这里错过了什么?我曾尝试搜索一篇没有运气的文章来解决这个问题。我还以为这是一个普遍的问题。

如果有任何不清楚的地方请告诉我,或者我可以提供更多信息。 谢谢, 戴夫

更新!!! 我刚刚发现了这个相关问题: 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);
        }


    }
}

不知道这对你是否可行,但如果你可以使用抽象 class 而不是接口,你可以做的是将 == 运算符实现为对抽象 Equals( ).

这样任何人在派生的 class 上使用 == 都会得到与调用 Equals 相同的结果。

应用于两个接口引用的

operator ==operator != 比较引用,因为这些接口没有运算符重载的可能性,因为它们是静态方法。

CLR 无法调用它们。

How do I override the equals operator == for an Interface in C#?

的副本