Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 在不同的泛型实例化中实现相同的接口_F#_Interface_Generics - Fatal编程技术网

F# 在不同的泛型实例化中实现相同的接口

F# 在不同的泛型实例化中实现相同的接口,f#,interface,generics,F#,Interface,Generics,在C#中,我可以使用两个不同的类型参数在一个类上实现两次泛型接口: 接口IFoo{void Foo(tx);} 类栏:IFoo,IFoo { 公共void Foo(int x){} 公共void Foo(float y){} } 我想在F#做同样的事情: 类型IFoo单元 类型栏()= 接口IFoo与 [] 成员this.Foo x=() 接口IFoo与 [] 成员this.Foo x=() 但它给出了一个编译器错误: 此类型在不同的泛型实例化'IFoo'和'IFoo'中实现或继承相同的接口

在C#中,我可以使用两个不同的类型参数在一个类上实现两次泛型接口:

接口IFoo{void Foo(tx);}
类栏:IFoo,IFoo
{
公共void Foo(int x){}
公共void Foo(float y){}
}
我想在F#做同样的事情:

类型IFoo单元
类型栏()=
接口IFoo与
[]
成员this.Foo x=()
接口IFoo与
[]
成员this.Foo x=()
但它给出了一个编译器错误:

此类型在不同的泛型实例化
'IFoo'
'IFoo'
中实现或继承相同的接口。此版本的F#中不允许这样做

我在网上找不到。是否出于某种原因而不赞成这种使用?有没有计划在即将发布的F#中允许这样做?

现在我不知道有没有计划允许这样做。。该功能和至少部分(见注释)在F#4.0中实现

我认为它目前不被允许的唯一原因是它的实现非常繁琐(特别是对于F#type推断),而且在实践中很少出现(我只记得有一位客户询问过这一点)

考虑到无限的时间和资源,我认为这是允许的(我可以想象这会被添加到该语言的未来版本中),但现在看来这似乎不值得支持。(如果你知道一个强有力的激励案例,请发邮件fsbugs@microsoft.com.)

编辑

作为一个好奇的实验,我写了这个C#:

公共接口 { 空隙F(tx); } 公共类雪茄:IG,IG { 公共void F(int x){Console.WriteLine(“int”);} 公共void F(字符串x){Console.WriteLine(“str”);} } 并从F#中引用了它(带有建议结果的注释)

let cig=new cig()
让idunno=cig:>IG//键入IG,猜猜是否只选择“第一个”接口?
设ii=cig:>IG//
ii.F(42)//打印“int”
让is=cig:>IG//起作用
is.F(“foo”)//打印“str”

因此,这就是通常在这个“边界”上发生的事情,F#-F#可以使用这些东西,即使您不能从语言内部编写相同的东西。

有一个合理但不优雅的方法,为每个接口创建一个新类型这里是一个从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)
键入public nSvcBusEvents()=
成员this.HandleEvents(msg:IEvent)=()
//处理消息ie:let json=JsonConvert.SerializeObject(msg)
键入public ActionLoggedHandler()=
接口IHandleMessages与
成员this.Handle(msg:ActionLoggedEvent)=
nSvcBusEvents().HandleEvents(msg)
键入public ActionCompletedHandler()=
接口IHandleMessages与
成员this.Handle(msg:ActionCompletedHandler)=
nSvcBusEvents().HandleEvents(msg)
键入public ActionFailedHandler()=
接口IHandleMessages与
成员this.Handle(msg:ActionFailedHandler)=
nSvcBusEvents().HandleEvents(msg)

Er,那么F#类型推断如何处理用C#编写的此类类型呢?至于理由,那么。。。ECMA CLI规范定义了各种类别的CLS合规性;其中之一是“CLS扩展器”。其中一个要求是:“能够……实现任何符合CLS的接口。”要扩展Pavel的评论,如果在C#中定义一个非通用接口
I
,它扩展了
IG
IG
,会发生什么?这个接口可以从F#中实现吗?@kvb,不,这个接口不能从F#中实现。这就是处理面向对象的事件处理系统的方式,例如,实现IHandleHere的一个案例:我正在实现一个IDictionary,它也需要迭代,因为为F#4.0 Pull请求计划的ICollectionFeature可以在以下位置找到:
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"); }
}
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"
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)