【问题标题】:Compare 2 interfaces比较 2 个接口
【发布时间】:2011-06-29 23:11:23
【问题描述】:
interface I //: IEquatable<I>
{ }

class A : I
{
    static public bool operator !=(A a, I i)
    {
        return !(a == i);
    }

    static public bool operator ==(A a, I i)
    {
        return true;
    }

    public override bool Equals(object obj)
    {
        if (obj is I)
            return this == (I)obj;
        else
            return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

class B : I
{
    static public bool operator !=(B b, I i)
    {
        return !(b == i);
    }

    static public bool operator ==(B b, I i)
    {
        return false;
    }

    public override bool Equals(object obj)
    {
        if (obj is I)
            return this == (I)obj;
        else
            return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        List<I> iss = new List<I>();
        A a = new A();
        B b = new B();
        iss.Add(a);
        iss.Add(b);

        if (iss[0] == iss[1])
            Console.WriteLine("a == b");
        else
            Console.WriteLine("a != b");

        if (iss[1] == iss[0])
            Console.WriteLine("b == a");
        else
            Console.WriteLine("b != a");
    }
}

输出是

a != b
b != a

我期待

a == b
b != a

谁能解释一下?

【问题讨论】:

    标签: .net oop operators operator-overloading


    【解决方案1】:

    我会在每个类的 Equals() 方法和 == 运算符中设置一个断点,然后查看调用什么来评估每个表达式。这显然不是你所期望的。我的猜测是,因为I 没有也不能要求实现者公开== 运算符,当你正在比较两个Is 时,运行时不会费心寻找重载的运算符,而是求助于System.Object ==,它执行引用检查。

    【讨论】:

    • 接口不能有操作符...但是如果我需要强制比较两个我呢?
    • 要求 I 的实现者公开一个命名方法,如“SemanticallyEquals(I other)”。然后,无论您将对象视为 Is 还是 As 和 B,此方法在该继承级别(而不是 Object)都可用,因此可以保证调用遵循您的继承层次结构,而不是查找快捷方式。
    • 为什么不让接口扩展IEquatable&lt;I&gt;
    • @Mark Sowul:如您所见,您的建议已在我的代码中注释...不起作用,您可以对其进行测试。我需要 A==我是真的,B==我 - 假的。
    • 我的评论是为了回应 Keith 对 SemanticallyEquals 的建议。您不应该为此使用 == ,因为您寻求语义平等,而不是引用平等。见这里msdn
    【解决方案2】:

    简单回答:

    您有一个List&lt;I&gt;,并且您将两个I 相互比较。因为interface I 没有(也不能)实现比较运算符,所以对象通过引用进行比较。

    相反,您可以使用抽象基类:

    public interface I
    {
    }
    
    public abstract class AbstractI : I
    {
        public static bool operator ==(AbstractI left, I right)
        {
            return left.equals(right); //TODO can be null
        }
        public static bool operator !=(AbstractI left, I right)
        {
            return !left.equals(right);
        }
    
        protected abstract bool equals(I other);
    }
    
    public class A : AbstractI
    {
        protected override bool equals(I other)
        {
            //TODO your compare code here
            throw new NotImplementedException();
        }
    }
    
    public class B : AbstractI
    {
        protected override bool equals(I other)
        {
            //TODO your compare code here
            throw new NotImplementedException();
        }
    }
    
    
    List<AbstractI> l = new List<AbstractI>(){
        new A(),
        new B()
    };
    
    var x = l[0] == l[1];
    

    【讨论】:

    • 接口不能有操作符...但是如果我需要比较两个我呢?
    • 如果您尝试比较两个对象是否实现相同的接口,请尝试使用 is 关键工作。您应该能够执行 if(A is I && B is I) 之类的操作。不太确定这是否是您正在寻找的东西。
    • 您可能会以静态比较方法或抽象基类而不是接口结束。
    • @cptScarlet:不,这不是关于Is,也不是关于测试接口实现。是关于比较 2 个对象,而不是它们的类型。
    • @matthias.lukaszek:那么,如何将此静态方法“附加”到标准对象比较(使用 ==)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多