Error del compilador en F#4?
(2)
Tengo alguna fuente F # 4.0 que compila bien en la depuración, pero no en la versión.
No hay definiciones condicionales, no hay cambios en los tipos inferidos, y no puedo pensar en nada más que pueda explicarme esta diferencia.
¿Realmente me topé con un error de compilación?
Este es un fragmento con el código problemático.
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 ->
El mensaje de error se refiere al último uso de "oldItems", antes de la palabra clave "with" al final de la línea larga. El mensaje de error es:
Valor no definido ''oldItems: UserDisplayItem list''
¿¡Qué!? oldItems está a la vista unas pocas líneas arriba, y esto se compila en Debug, ¿por qué no en Release? ¿Qué significa realmente ese mensaje de error?
UserDisplayItem es una clase simple. newItems es un ResizeArray de UserDisplayItem
Miré en el historial de compilación, y compilé bien en Liberar cuando UserDisplayItem era un registro inmutable F #, y no una clase.
Visual Studio 2015, F # 4.0, cualquier CPU, lanzamiento, .NET 4.5.2 apuntado.
ACTUALIZAR:
El siguiente es un ejemplo completo. Puede crear una aplicación de consola F # y pegarla en Program.fs. Espero que se compile en Debug, pero no en 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 -> ()
ACTUALIZACIÓN 2:
Una muestra aún más corta.
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 -> ()
Hasta que tenga la solución para este problema (consulte la respuesta de DAXaholic para la solución final), puede usar esta solución, tal como se explica en dsyme aquí:
https://github.com/Microsoft/visualfsharp/issues/759#issuecomment-162243299
El arreglo aplicado a la última muestra en la pregunta. Primero agrega esto.
// do something that doesn''t get optimized away
let workaround() = null |> ignore
y luego solo agregue una llamada a la función de solución en el (los) lugar (s) correcto (s), que está justo antes de cualquier bucle donde se produce este error.
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