tipos studio nivel manejo los funcion eventos alto events interface f#

events - studio - ¿Cómo se debe declarar un evento en una interfaz F#?



onclicklistener android studio (2)

La forma estándar de publicar eventos en F # ahora parece ser la siguiente:

type MyDelegate = delegate of obj * EventArgs -> unit type MyType () = let myEvent = new Event<MyDelegate, EventArgs> () [<CLIEvent>] member this.OnMyEvent = myEvent.Publish

y eso funciona bien, incluso poder consumir ese evento desde otros lenguajes .NET (C # al menos lo que he probado). Pero, ¿cómo puedes hacer que ese evento aparezca en una interfaz? Esto es lo que estoy tratando ...

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

Pero eso no se compilará, el miembro dentro de la interfaz causa un error: "No se encontró un miembro abstracto o de interfaz que corresponda a esta anulación". ¿Cómo debo declarar el evento en mi interfaz? ¿O es que mi sintaxis de miembro es incorrecta?

Nota: no se trata de consumir eventos C # en F # o uso general de eventos en F #: el aspecto de la interfaz es clave.


Además de la respuesta del thr, también es válido escribir código que no use el atributo CLIEvent tanto en la interfaz como en la implementación:

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

La razón de esto es que el compilador F # puede compilar eventos de dos maneras:

  • Cuando especifica el atributo, el evento se compila en un evento .NET (compatible con C #) con operaciones subyacentes de add y remove .

  • Cuando no especifica el atributo, el evento se compila como una propiedad .NET (con get ) que devuelve un valor de tipo IEvent<''T> (definido en la biblioteca principal de F #)

Entonces, la definición de la interfaz debe coincidir con la implementación (lamentablemente, inferir esto automáticamente es bastante complicado, por lo que el compilador no lo hace).

¿Qué opción necesitas? Si está exponiendo el código a C #, entonces definitivamente necesita CLIEvent . Si lo está utilizando solo desde F #, entonces no importa demasiado. Sin embargo, podría ser más eficiente evitar usarlo cuando a menudo pasa el evento a las funciones, por ejemplo en myTyp.OnMyEvent |> Event.map (...)
(en la primera representación, el evento debe estar envuelto en un objeto IEvent<_> mientras que en el segundo caso, solo puede obtener el objeto utilizando la propiedad).


Debe especificar el atributo CLIEvent tanto en la interfaz como en la implementación.

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