The C# equivalent of what I'd like to declare is simple:
public event Action<DateTime, int> example;
I wish to subscribe to this event from C# as follows:
example += DoSomething;
private static void DoSomething(DateTime time, int count)
{
Console.WriteLine("Time: {0} Count:{1}", time, count);
}
I can use DelegateEvent
( see this question ), but my understanding is that DelegateEvent.Trigger
will result in the boxing of the values, as they're passed in as an object array.
How can I define an event of multiple parameters without boxing in F#?
The concrete implementation of DelegateEvent
does box the arguments into an obj[]
, but you can create your own IDelegateEvent
type instead:
type T() =
let handlers = ResizeArray<System.Action<System.DateTime,bool>>()
let event = { new IDelegateEvent<_> with
member __.AddHandler(h) = handlers.Add h
member __.RemoveHandler(h) = handlers.Remove h |> ignore }
[<CLIEvent>]
member x.example = event
member x.Trigger(dt,i) =
for handler in handlers do
handler.Invoke(dt,i)
If this is something you'll do a lot, then you could encapsulate the logic into its own CustomEvent
type rather than spreading it through the type containing the event.
[<Struct>]
type MyEventArgs(date:DateTime,number:int) =
member x.Date = date
member x.Number = number
type MyClass() =
let e = new Event<_>()
[<CLIEvent>]
member x.OnEvent = e.Publish
member private this.FireEvent (s:DateTime) (i:int) =
e.Trigger (MyEventArgs(s,i))
Then from C#:
namespace Test
{
class MainClass
{
public static void Main (string[] args)
{
MyClass c = new MyClass ();
c.OnEvent += (object sender, MyLib.EventArgs a) =>
Console.WriteLine("Hello from F#");
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.