问题描述
此F#代码段
let rec reformat = new EventHandler(fun _ _ ->
b.TextChanged.RemoveHandler reformat
b |> ScrollParser.rewrite_contents_of_rtb
b.TextChanged.AddHandler reformat
)
b.TextChanged.AddHandler reformat
导致以下警告:
有没有一种方法可以重写代码来避免此警告?还是在F#中没有洁净的递归对象的方式?
Is there a way in which the code can be rewritten to avoid this warning? Or is there no kosher way of having recursive objects in F#?
推荐答案
您的代码是构造递归对象的完美方法.编译器会发出警告,因为它不能保证在初始化引用之前不会访问该引用(这将导致运行时错误).但是,如果您知道EventHandler
在构造期间未调用提供的lambda函数(不会),则可以放心地忽略该警告.
Your code is a perfectly fine way to construct a recursive object. The compiler emits a warning, because it cannot guarantee that the reference won't be accessed before it is initialized (which would cause a runtime error). However, if you know that EventHandler
does not call the provided lambda function during the construction (it does not), then you can safely ignore the warning.
举一个警告实际上表明有问题的示例,您可以尝试以下代码:
To give an example where the warning actually shows a problem, you can try the following code:
type Evil(f) =
let n = f()
member x.N = n + 1
let rec e = Evil(fun () ->
printfn "%d" (e:Evil).N; 1)
Evil
类在构造函数中采用一个函数,并在构造期间将其称为 .结果,lambda函数中的递归引用尝试在将e
设置为值之前进行访问(并且您会收到运行时错误).但是,尤其是在使用事件处理程序时,这不是问题(当正确使用递归对象时,您会得到警告).
The Evil
class takes a function in a constructor and calls it during the construction. As a result, the recursive reference in the lambda function tries to access e
before it is set to a value (and you'll get a runtime error). However, especially when working with event handlers, this is not an issue (and you get the warnning when you're using recursive objects correctly).
如果要摆脱警告,可以使用显式的ref
值和null
重写代码,但是如果没有警告和带有更丑陋的代码:
If you want to get rid of the warning, you can rewrite the code using explicit ref
values and using null
, but then you'll be in the same danger of a runtime error, just without the warning and with uglier code:
let foo (evt:IEvent<_, _>) =
let eh = ref null
eh := new EventHandler(fun _ _ ->
evt.RemoveHandler(!eh) )
evt.AddHandler(!eh)
这篇关于F#中的递归对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!