我有一些F#4.0源代码在Debug中编译良好,但在Release中没有.
没有条件定义,推断类型没有变化,也没有其他我能想到的,这可以解释这个差异给我.
我是否真的偶然发现了编译器错误?
这是一个有问题的代码片段.
let oldItems = userDisplayItems |> Seq.toList
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplay.UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
| Some oldItem ->
Run Code Online (Sandbox Code Playgroud)
错误消息指的是最后一次使用"oldItems",在长行末尾的"with"关键字之前.错误消息是:
未定义的值'oldItems:UserDisplayItem list'
什么!?oldItems在上面几行显而易见,这在Debug中编译,为什么不在Release中呢?该错误消息实际上意味着什么?
UserDisplayItem是一个简单的类.newItems是UserDisplayItem的ResizeArray
我查看了构建历史,当UserDisplayItem是F#immutable记录而不是类时,它在Release中编译得很好.
Visual Studio 2015,F#4.0,任何CPU,Release,.NET 4.5.2都是针对性的.
更新:
以下是一个完整的例子.您可以创建一个F#控制台应用程序,并将其粘贴到Program.fs中.我希望它将在Debug中编译,但不会在Release中编译.
open System.Collections.ObjectModel
type User = { Id: int }
[<AllowNullLiteral>]
type UserDisplayItem(id: int) =
let mutable id = id
member x.Id with get() = id and set(v) = id <- v
let userDisplayItems = new ObservableCollection<UserDisplayItem>()
let refreshList () =
let newItems = userDisplayItems
let oldItems = userDisplayItems |> Seq.toList
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
| Some oldItem -> ()
| None -> ()
Run Code Online (Sandbox Code Playgroud)
更新2:
更短的样本.
type UserDisplayItem = { Id: int }
let refreshList () =
let newItems = new ResizeArray<UserDisplayItem>()
let oldItems = new ResizeArray<UserDisplayItem>() |> Seq.toList
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
| Some oldItem -> ()
| None -> ()
Run Code Online (Sandbox Code Playgroud)
在您解决此问题之前(请参阅DAXaholic的最终修复答案),您可以使用此解决方法,如dsyme所述:
https://github.com/Microsoft/visualfsharp/issues/759#issuecomment-162243299
该修复程序应用于问题中的最后一个示例.首先添加这个.
// do something that doesn't get optimized away
let workaround() = null |> ignore
Run Code Online (Sandbox Code Playgroud)
然后只在正确的位置添加对函数变通方法的调用,这是在任何出现此错误的循环之前.
let oldItems = new ResizeArray<UserDisplayItem>() |> Seq.toList
workaround()
for newItem in newItems do
match List.tryFind (fun (itemOfOld: UserDisplayItem) -> itemOfOld.Id = newItem.Id) oldItems with
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
316 次 |
| 最近记录: |