2011-02-18 76 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 '? –