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

问题描述 投票:-1回答:1

我继承了一些代码,其中Equals被覆盖,但不是==。我解决了这个问题,但是发现了更多问题。在调用代码中,对象是使用接口构造的,然后进行比较,结果与预期不符。我在下面放了一个完整的最小示例。简而言之,给定ISilly i1 = new Silly()和ISilly i2 = new Silly,i1 == i2返回false,而不是true。有没有办法解决这个问题,我应该吗?我看到一些类似“ i1和i2是接口的论点。可能有很多类是从ISilly派生的,所以请问i1和i2是否仅在引用相等的意义上才有意义”。如果是的话,我的两个问题是:

  1. 为什么Equals如此出色?
  2. 如何阻止应用程序程序员调用“ i1 == i2”?比起i1.Equals(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);
        }


    }
}
c# inheritance interface equality
1个回答
0
投票

不知道是否有可能,但是如果您可以使用抽象类而不是接口,则可以将==运算符实现为对抽象Equals()的调用。

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

© www.soinside.com 2019 - 2024. All rights reserved.