我正在尝试添加&从Silverlight FrameworkElement中删除事件处理程序,但我无法使语法正确。
我想做这样的事情:
let clickedEventHandler = fun args -> printfn "Click!"
fe.MouseLeftButtonDown.AddHandler( clickedEventHandler)
...
fe.MouseLeftButtonDown.RemoveHandler(clickedEventHandler)
这样做的正确方法是什么?
答案 0 :(得分:6)
正如您已经提到的,您需要创建一个委托实例:
let ch = new MouseButtonEventHandler(fun obj args ->
printfn "Click!")
然后,您可以使用ch
作为AddHandler
或RemoveHanlder
的参数。原因是,F#函数值实际上并未表示为任何委托类型。它有自己的类型,不是委托(另请参阅another SO discussion)。如果您查看F#interactive(或VS IntelliSense)中的类型,您可以看到差异:
> (fun (o:obj) (a:MouseButtonEventArgs) -> printfn "Click!")
val it : obj -> MouseButtonEventArgs -> unit = (...)
> new MouseButtonEventHandler(fun o a -> printfn "Click!")
val it : MouseButtonEventHandler = (...)
可能令人困惑的是,F#还允许在调用方法时从lambda函数值隐式转换为兼容的委托类型,但是只有当你直接将lambda函数作为参数时才会起作用(我认为):
fe.MouseLeftButtonDown.AddHandler(fun obj args ->
printfn "Click!")
您仍然需要F#中的委托的另一个原因是委托具有明确定义的比较语义(它们与任何其他引用类型进行比较)。对于函数,F#规范没有说它们何时相等。
答案 1 :(得分:2)
在这种情况下,事实证明您可以执行以下操作:
let clickedEventHandler = new MouseButtonEventHandler(fun obj args -> printfn "Click!")
fe.MouseLeftButtonDown.AddHandler( clickedEventHandler)
...
fe.MouseLeftButtonDown.RemoveHandler(clickedEventHandler)