【问题标题】:How should an event be declared in an F# interface?应该如何在 F# 接口中声明事件?
【发布时间】:2012-11-14 14:16:37
【问题描述】:

现在在 F# 中发布事件的标准方式似乎如下:

type MyDelegate = delegate of obj * EventArgs -> unit

type MyType () =
    let myEvent = new Event<MyDelegate, EventArgs> ()

    [<CLIEvent>]
    member this.OnMyEvent = myEvent.Publish

而且效果很好,包括能够从其他 .NET 语言(至少我测试过的 C#)中使用该事件。但是如何让该事件显示在界面中呢?这就是我正在尝试的...

type MyDelegate = delegate of obj * EventArgs -> unit

type IMyType =
    abstract member OnMyEvent : IEvent<MyDelegate, EventArgs>

type MyType () =
    let myEvent = new Event<MyDelegate, EventArgs> ()

    interface IMyType with
        [<CLIEvent>]
        member this.OnMyEvent = myEvent.Publish

但这不会编译 - 接口中的成员会导致错误:“未找到与此覆盖对应的抽象或接口成员”。我应该如何在我的界面中声明事件?还是我的成员语法错误?

注意 - 这不是关于在 F# 中使用 C# 事件或在 F# 中使用一般事件 - 接口方面是关键。

【问题讨论】:

    标签: events interface f#


    【解决方案1】:

    您需要在接口和实现上都指定 CLIEvent 属性。

    open System;
    
    type MyDelegate = delegate of obj * EventArgs -> unit
    
    type IMyType =
        [<CLIEvent>]
        abstract member OnMyEvent : IEvent<MyDelegate, EventArgs>
    
    type MyType () =
        let myEvent = new Event<MyDelegate, EventArgs> ()
    
        interface IMyType with
            [<CLIEvent>]
            member this.OnMyEvent = myEvent.Publish
    

    【讨论】:

    • 真棒 - 不明显,但非常方便!谢谢。
    【解决方案2】:

    除了 thr 的回答之外,在接口和实现中编写不使用CLIEvent 属性的代码也是有效的:

    type MyDelegate = delegate of obj * EventArgs -> unit
    
    type IMyType =
        abstract member OnMyEvent : IEvent<MyDelegate, EventArgs>
    
    type MyType () =
        let myEvent = new Event<MyDelegate, EventArgs> ()    
        interface IMyType with
            member this.OnMyEvent = myEvent.Publish
    

    这样做的原因是F#编译器可以通过两种方式编译事件:

    • 当您指定属性时,该事件将被编译成一个带有底层addremove 操作的.NET 事件(与C# 兼容)。

    • 1234563 /p>

    因此,您的接口定义必须与实现匹配(遗憾的是,自动推断这一点非常棘手,因此编译器不会这样做)。

    您需要哪个选项?如果您要向 C# 公开代码,那么您肯定需要 CLIEvent。如果您只是从 F# 中使用它,那么它并不重要 - 但是,当您经常将事件传递给函数时避免使用它可能会更有效 - 例如在 myTyp.OnMyEvent |&gt; Event.map (...)
    (在第一种表示中,需要将事件包装到IEvent&lt;_&gt; 对象中,而在第二种情况中,它可以使用属性获取对象)。

    【讨论】:

    • Action&lt;obj,EventArgs&gt; 会代替 MyDelegate 工作吗?
    猜你喜欢
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 2010-09-24
    • 1970-01-01
    • 2019-02-15
    • 2014-03-28
    • 2014-06-25
    相关资源
    最近更新 更多