比较2个接口

时间:2011-02-18 16:46:37

标签: .net oop operators operator-overloading

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

有人可以解释一下吗?

2 个答案:

答案 0 :(得分:1)

我在每个类的Equals()方法和==运算符中设置断点,并查看调用每个表达式的内容。它显然不是你所期望的。我的猜测是,因为I不能并且不能要求实现者公开==运算符,所以当您正在比较两个I时,运行时不会打扰寻找重载的运算符,而是转向System.Object ==,它执行参考检查。

答案 1 :(得分:0)

简单回答:

您有一个List<I>并且您将两个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];