2011-02-18 74 views
1
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"); 
    } 
} 

输出是比较2个接口

a != b 
b != a 

我预计

a == b 
b != a 

可能有人能解释一下吗?

回答

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]; 
+0

接口不能有运营商...但如果我需要比较两个我的呢? – serhio

+0

如果您试图比较两个对象是否实现相同的界面,请尝试使用“关键”工作。你应该可以做一些事情,如果(A是I && B是I)。不太确定这是不是你正在寻找的。 – cptScarlet

+0

您可能会最终使用静态比较方法或抽象基类而不是接口。 –

1

我会设置一个断点在每个类的equals()方法和==操作符,看看被称为评估每个表达式。这显然不是你所期望的。我的猜测是,因为I不会要求实现者公开==运算符,所以当您比较两个I时,运行时不会寻找重载的运算符,而是使用System.Object ==,执行参考检查。

+0

接口不能有运算符......但是如果我*需要*强制比较两个我呢? – serhio

+0

要求I的实现者公开一个名为“SemanticallyEquals(I other)”的命名方法。然后,无论您将对象视为Is还是As和Bs,此方法在继承级别(而不是Object)都可用,因此调用将保证遵循继承层次结构,而不是找到快捷方式。 – KeithS

+0

为什么不只是让接口扩展'IEquatable '? –