[英]How should an event be declared in an F# interface?
現在,在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#中的一般事件使用 - 接口方面是關鍵。
您需要在接口和實現上指定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
除了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#編譯器可以通過兩種方式編譯事件:
當您指定屬性時,事件將被編譯為帶有基礎add
和remove
操作的.NET事件(與C#兼容)。
如果未指定該屬性,則會將事件編譯為.NET屬性(帶有get
),該屬性返回IEvent<'T>
類型的值(在F#核心庫中定義)。
因此,您的接口定義必須與實現相匹配(遺憾的是,自動推斷它非常棘手,因此編譯器不這樣做)。
你需要哪個選項? 如果您將代碼暴露給C#,那么您肯定需要CLIEvent
。 如果你只是從F#中使用它,那么它並不重要 - 但是,當你經常將事件傳遞給函數時,避免使用它可能更有效 - 例如在myTyp.OnMyEvent |> Event.map (...)
(在第一種表示中,事件需要包裝到IEvent<_>
對象中,而在第二種情況下,它可以使用屬性獲取對象)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.