2009-09-23 91 views
16

在C#中相同的接口,我可以在一個類中實現通用接口的兩倍,使用兩種不同類型的參數:實現在不同類屬實例

interface IFoo<T> { void Foo(T x); } 

class Bar : IFoo<int>, IFoo<float> 
{ 
    public void Foo(int x) { } 
    public void Foo(float y) { } 
} 

我想這樣做在F#同樣的事情:

type IFoo<'a> = abstract member Foo : 'a -> unit 

type Bar() = 
    interface IFoo<int> with 
     [<OverloadID("int")>] 
     member this.Foo x =() 

    interface IFoo<float> with 
     [<OverloadID("float")>] 
     member this.Foo x =() 

但它給一個編譯器錯誤:

This type implements or inherits the same interface at different generic instantiations 'IFoo<float>' and 'IFoo<int>' . This is not permitted in this version of F#.

我找不到任何discussion of this issue在網絡上。這種用法因爲某種原因而皺眉嗎?是否有計劃在即將發佈的F#版本中允許這樣做?

+0

功能計劃在F#4.0 http://fslang.uservoice.com/forums/245727- f-language/suggestions/5663504-allow-to-implement -with-same-interface-at- – foobarcode 2014-10-19 20:01:31

+0

Pull Request可在以下網址找到:https://github.com/Microsoft/visualfsharp/pull/18 – forki23 2015-01-16 11:24:45

回答

11

現在我不知道有計劃允許這樣做。 。功能has been planned,至少部分(見註釋)在F#4.0中實現。我認爲目前不允許使用的唯一原因是實現(特別是使用F#類型推斷)並非微不足道,而且它在實踐中很少出現(我只記得有一位客戶曾問過這個問題)。

考慮到無限的時間和資源,我認爲這將被允許(我可以想象這將被添加到該語言的未來版本),但現在看起來這似乎不是一個值得努力的功能的配套。 (如果你知道一個強大的激勵的情況下,請郵寄[email protected]

編輯

作爲一個實驗的好奇,我寫了這個C#:

public interface IG<T> 
{ 
    void F(T x); 
} 
public class CIG : IG<int>, IG<string> 
{ 
    public void F(int x) { Console.WriteLine("int"); } 
    public void F(string x) { Console.WriteLine("str"); } 
} 

,並從引用它F#(與意見建議的結果)

let cig = new CIG() 
let idunno = cig :> IG<_> // type IG<int>, guess just picks 'first' interface? 
let ii = cig :> IG<int> // works 
ii.F(42)     // prints "int" 
let is = cig :> IG<string> // works 
is.F("foo")    // prints "str" 

所以這是通常的情況與F#這個「邊界」的東西 - F#可以消耗這東西好,即使你不能創作的SA我從語言中得到東西。

+2

呃,那麼那麼F#類型推理如何處理用C#編寫的類型呢?至於基本原理,那麼...... ECMA CLI規範定義了CLS遵從的各種類別;其中之一是「CLS延長器」。其中一個要求是:「能夠......實現任何符合CLS的接口。」 – 2009-09-23 07:34:25

+0

若要擴展Pavel的評論,如果在C#中定義非泛型接口'I',會發生什麼情況,它會同時擴展'IG '和'IG '?這個接口可以在F#中實現嗎? – kvb 2009-09-23 13:49:58

+0

@kvb,不,該接口不能從F#實現。 – Brian 2009-09-23 17:06:28

0

有一個合理的,但不是優雅的方式來做到這一點,爲每個接口創建一個新類型是一個從ESB(nSvcBus)中消耗多個事件的示例,它要求每個事件對應一個已實現的接口。下面的第一個類型包含通用的「處理」的代碼,其他類型的只是實現該接口並調用到通用處理器

type public nSvcBusEvents() = 

    member this.HandleEvents(msg:IEvent) =() 
     //handle messages ie: let json = JsonConvert.SerializeObject(msg) 

type public ActionLoggedHandler() = 
    interface IHandleMessages<Events.ActionLoggedEvent> with 
     member this.Handle(msg : ActionLoggedEvent) = 
      nSvcBusEvents().HandleEvents(msg) 

type public ActionCompletedHandler() = 
    interface IHandleMessages<Events.ActionCompletedHandler> with 
     member this.Handle(msg : ActionCompletedHandler) = 
      nSvcBusEvents().HandleEvents(msg) 

type public ActionFailedHandler() =  
    interface IHandleMessages<Events.ActionFailedHandler> with 
     member this.Handle(msg : ActionFailedHandler) = 
      nSvcBusEvents().HandleEvents(msg)