2012-12-19 64 views
11

拿這個例子:在C#中,爲什麼接口實現必須顯式地實現另一個方法的版本?

public interface IFoo 
{ 
    IFoo Bar(); 
} 

public class Foo : IFoo 
{ 
    public Foo Bar() 
    { 
     //... 
    } 

    IFoo IFoo.Bar() { return Bar(); } //Why is this necessary? 
} 

爲什麼是必要的IFoo Bar()隱含執行,即使Foo轉換爲IFoo沒有投?

+0

你爲什麼這樣做呢?你實際上將'Foo'的用戶綁定到具體的實現上,使得單元測試的嘲弄變得困難,並且通常會增加應用程序中的耦合... –

+0

這兩種方法幾乎是相互獨立的。兩者都有效,但有不同的目的。你不會在同一個具體類中爲同一個接口使用這兩種方法(至少不是我能想到的) – dkackman

+0

@SteveCzetty因此OP的問題;明確實現接口是必要的。 –

回答

4

你可以解決它像這樣(有點難看,但需要強類型的護理):

public interface IFoo<T> where T : IFoo<T> 
{ 
    T Bar(); 
} 

public class Foo : IFoo<Foo> 
{ 
    public Foo Bar() 
    { 
     //... 
    } 
} 
+1

Большоеспасибо,תודהרבה! – Matt

+0

由於沒有非泛型'IFoo'接口,因此不編譯。 –

+0

你是對的,我編輯了代碼。 –

3

因爲你可能不會總是希望實現該接口的行爲方式與具有相同簽名的方法的另一個版本相同的方法。

您可能還需要一個類來實現一個接口,但該方法不能從該類本身的一個實例訪問的方法。

5

微軟對這個問題的detailed write up,但它歸結爲多種接口/類已經在他們的相同方法實施。在此情況下,隱含不再起作用

class Test 
{ 
    static void Main() 
    { 
     SampleClass sc = new SampleClass(); 
     IControl ctrl = (IControl)sc; 
     ISurface srfc = (ISurface)sc; 

     // The following lines all call the same method. 
     sc.Paint(); 
     ctrl.Paint(); 
     srfc.Paint(); 
    } 
} 


interface IControl 
{ 
    void Paint(); 
} 
interface ISurface 
{ 
    void Paint(); 
} 
class SampleClass : IControl, ISurface 
{ 
    // Both ISurface.Paint and IControl.Paint call this method. 
    public void Paint() 
    { 
     Console.WriteLine("Paint method in SampleClass"); 
    } 
} 

// Output: 
// Paint method in SampleClass 
// Paint method in SampleClass 
// Paint method in SampleClass 

如果我們採取明確的方法,我們最終會得到這個結果。

public class SampleClass : IControl, ISurface 
{ 
    void IControl.Paint() 
    { 
     System.Console.WriteLine("IControl.Paint"); 
    } 
    void ISurface.Paint() 
    { 
     System.Console.WriteLine("ISurface.Paint"); 
    } 
} 

這一切歸結爲提供唯一性,當實施類型衝突。在你的例子中,FooIFoo

+0

是的,但這裏只有一個接口。 – Matt

+0

這不回答關於返回類型的問題。 –

+0

@Matt微調了一下,注意單個界面正在發揮作用,但該類還實現了該方法簽名。 –

5

它需要在這種情況下,因爲C#不支持返回類型協方差接口,因此你的函數

public Foo Bar() 
{ 
    //... 
} 

不滿足,因爲Bar方法的返回類型的IFoo接口是不同的。

既然你也想實現的接口,你唯一的選擇是明確這樣做,因爲你已經在類中定義的方法Bar()

+0

是的,但**爲什麼**不C#允許這? –

+2

@IlyaKogan - 我不知道C#爲什麼不支持返回類型協變 - 你不得不問設計師。 C#通常更喜歡事物是明確的,所以它可能會阻止接口意外地被隱式實現。 – Lee

+1

@IlyaKogan這可以追溯到_why_關於實現的每個問題;因爲他們選擇了。 –

0

我建議你保持隱式執行的保護,而不是公衆。

public class Foo : IFoo 
{ 
    **protected virtual** Foo Bar() 
    { 
     //... 
    } 

    IFoo IFoo.Bar() { return Bar(); } 
} 

有爲什麼/時,在這個線程使用顯式實現相當廣泛的答案:

implicit vs explicit interface implementation

一個很好的理由使用明確的實現,你可以很容易地使用依賴注入當你使用你的Foo類的時候有更鬆散的耦合。

相關問題