Events enable you to associate function calls with user actions and are important in GUI programming. Events can also be triggered by your applications or by the operating system.
In F#, you can create and use events through F#'s Event class.
The following example creates an event using the Event
constructor.
type Author(name : string) =
let mutable _name = name;
let nameChanged = new Event<string>()
member this.Name
with get() = _name
and set(value) = _name <- value
To allow listeners to hook onto your event, we need to expose the nameChanged
field as a public member using the event's Publish
property as shown below.
type Author(name : string) =
let mutable _name = name;
//creates event
let nameChanged = new Event<unit>()
//exposed event handler
member this.NameChanged = nameChanged.Publish
member this.Name
with get() = _name
and set(value) =
_name <- value
//invokes event handler
nameChanged.Trigger()
Now, any object can listen to the changes in the author's method.
It is very easy to add callbacks to event handlers. Each event handler has the type IEvent<'T>
which exposes several methods.
let p = new Author("Mark")
p.NameChanged.Add(fun () -> printfn "-- Name changed! New name: %s" p.Name)
printfn "Event handling is easy"
p.Name <- "Andy"
printfn "It handily decouples objects from one another"
p.Name <- "John"
p.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!")
printfn "It's also causing programs to behave non-deterministically."
p.Name <- "Mike"
printfn "The function NameChanged is invoked effortlessly."
Now when you execute the above code you will see the following output.
Event handling is easy
-- Name changed! New name: Andy
It handily decouples objects from one another
-- Name changed! New name: John
It's also causing programs to behave non-deterministically.
-- Name changed! New name: Mike
-- Another handler attached to NameChanged!
The function NameChanged is invoked effortlessly.
When multiple callbacks are connected to a single event, they are executed in the order they are added. However, in practice, you should not write code with the expectation that events will trigger in a particular order, as doing so can introduce complex dependencies between functions.