[英]Operator overloading on class that implements interface
假設我有一個接口IFoo和一個實現IFoo的類Foo。 我想定義自己的邏輯,根據它們包含的數據確定2個Foo實例是否相等,並重載==和!=運算符,以便在使用Foo時易於使用。
如果我有2個Foo實例,都存儲為Foo,則可以正常工作。 但是,如果我有兩個實例都存儲為IFoo,則突然不再調用我的重載運算符。 此外,由於我無法在IFoo接口上定義運算符,並且Foo運算符重載中的至少一個參數必須為Foo類型,因此我看不到有任何方法可以成功使我的類型重載該運算符。 這個對嗎?
另外,任何人都可以弄清為什么會這樣嗎? 通常,我希望將我的Foos存儲為IFoos與確定調用哪個相等函數無關,因為從根本上說,它們仍然是Foos!
任何幫助真的很感激
謝謝
編輯:好的,因為我的意思似乎有些混亂,所以這里有一個例子,希望可以澄清一下:
public interface IFoo
{
}
public class Foo : IFoo
{
public static bool operator==(Foo left, Foo right)
{
....
}
}
Foo foo1 = new Foo();
Foo foo2 = new Foo();
bool comparison1 = foo1 == foo2 //This is successfully calling the overloaded operator
IFoo ifoo1 = foo1;
IFoo ifoo2 = foo2;
bool comparison2 = ifoo1 == ifoo2 //This isn't
運算符重載僅在編譯時存在,編譯后僅是對具有已知名稱的特定靜態方法的調用。
C#編譯器可以識別Foo
運算符重載,並用Foo.op_Equality(a,b)
替換a == b
。 這意味着編譯后,類Foo中存在非虛擬靜態方法op_Equality
。 因此,不可能重載接口的運算符-接口不能具有靜態方法。 而且,運算符方法是非虛擬的 ,這意味着實際方法是從變量類型而不是值的類型解析的,因此編譯器將基於a
和b
變量類型尋找可能的運算符重載,如果它們都是IFoo
,則它將只能在IFoo
類型中查找op_Equality
不能擁有它。
您只能為基於值類型解析的方法提供自定義邏輯-這些是虛擬方法,例如,您可以為Foo類型覆蓋Equals方法,但是如果使用IFoo a == IFoo b
無濟於事。解析為Object.ReferenceEquals(a,b)
基本上是Aloraman所說的,但是讓我用另一種方式看一下它是否變得更加清晰。
當您有兩個聲明為IFoo的變量,但是將它們實例化為Foo對象時,變量聲明定義了語法檢查中可用的變量。 變量聲明在那里供編譯器查看,但是實例化直到執行才發生,實例化就不會出現,因此編譯器無法看到它們實際上是兩個Foo對象。 因為IFoo沒有並且不能有重載的運算符==,所以編譯器正確地將其視為錯誤。
當編譯器試圖弄清楚用於某種操作的內容時,它不能知道那些對象實際上是Foo,因為分配這些IFoo變量以包含Foo對象是在執行期間發生的。 當您比較這兩個IFoo變量時,編譯器無法理解您的真正意圖是使用實現IFoo和重載==的一個類。
但是,當將變量定義為Foo時,編譯器就完全知道,在執行時,實例化它們時,必須將它們實例化為Foo類型,並且它確切地知道在哪里編譯==運算符。
基本上,編譯器在嘗試編譯==運算符時,不會遍歷所有其他代碼來查看如何實例化這兩個操作數。 如果將它們定義為IFoo,則它將是僅有的信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.