Ответ 1
Кажется, это ошибка компилятора (возможно, связанная с 1020).
Может воспроизвести его с кодом и F # версии 14.0.23413.0
Теперь установлен текущий preview, который является F # версии 14.0.23618.0, и он работает.
У меня есть источник 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 ->
Сообщение об ошибке относится к последнему использованию "oldItems" перед ключевым словом "with" в конце длинной строки. Сообщение об ошибке:
Undefined значение 'oldItems: список UserDisplayItem'
Что!? oldItems находится на виду несколько строк выше, и это компилируется в Debug, так почему бы не в Release? Что означает это сообщение об ошибке?
UserDisplayItem - простой класс. newItems - это ResizeArray of UserDisplayItem
Я просмотрел историю сборки и отлично компилировался в Release, когда UserDisplayItem был неизменяемой записью F #, а не классом.
Visual Studio 2015, F # 4.0, любой CPU, Release,.NET 4.5.2.
UPDATE:
Ниже приведен полный пример. Вы можете создать консольное приложение 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 -> ()
ОБНОВЛЕНИЕ 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 -> ()
Кажется, это ошибка компилятора (возможно, связанная с 1020).
Может воспроизвести его с кодом и F # версии 14.0.23413.0
Теперь установлен текущий preview, который является F # версии 14.0.23618.0, и он работает.
Пока у вас не будет исправления этой проблемы (см. DAXaholic ответ для окончательного исправления), вы можете использовать это обходное решение, как объясняется здесь dsyme:
https://github.com/Microsoft/visualfsharp/issues/759#issuecomment-162243299
Исправление применяется к последнему образцу в вопросе. Сначала добавьте это.
// do something that doesn't get optimized away
let workaround() = null |> ignore
а затем добавьте только вызов обходного пути функции в нужном месте (точках), которое находится прямо перед любым циклом, где вы получаете эту ошибку.
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