这段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下列警告的结果:
traynote.fs(62,41):警告FS0040:将通过使用延迟引用在运行时检查对所定义对象的此引用和其他递归引用的初始化是否合理。这是因为您定义的是一个或多个递归对象,而不是递归函数。这个警告可以通过使用‘40’或‘--现在’40‘来抑制。
是否有方法可以重写代码以避免此警告?或者在F#中没有更好的方法来拥有递归对象?
发布于 2011-12-26 16:39:16
您的代码是构造递归对象的非常好的方法。编译器会发出警告,因为它不能保证在初始化引用之前不会访问它(这会导致运行时错误)。但是,如果您知道EventHandler在构造过程中没有调用提供的lambda函数(它不调用),那么您可以安全地忽略警告。
要给出警告实际显示问题的示例,您可以尝试以下代码:
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 (您将得到一个运行时错误)。但是,特别是在使用事件处理程序时,这不是一个问题(当您正确地使用递归对象时,您会得到警告)。
如果您想消除警告,可以使用显式ref值和null重写代码,但是运行时错误的危险是相同的,只是没有警告,代码更丑:
let foo (evt:IEvent<_, _>) =
let eh = ref null
eh := new EventHandler(fun _ _ ->
evt.RemoveHandler(!eh) )
evt.AddHandler(!eh)https://stackoverflow.com/questions/8636630
复制相似问题