簡體   English   中英

運算符在實現接口的類上重載

[英]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 因此,不可能重載接口的運算符-接口不能具有靜態方法。 而且,運算符方法是非虛擬的 ,這意味着實際方法是從變量類型而不是值的類型解析的,因此編譯器將基於ab變量類型尋找可能的運算符重載,如果它們都是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM