Blick Lassen Sie uns auf die Unterschiede zwischen den beiden Ansätzen:
Im ersten Fall, erstellen Sie eine Liste:
[ TypeB(), true; TypeB(), false ]
Dieser (TypeB * bool) list
Typ hat.
Die dict-Funktion hat den Typ seq<'Key * 'Value> -> IDictionary<'Key,'Value> (requires equality)
.
Folglich unter Anwendung der Funktion dict
dict [ TypeB(), true; TypeB(), false ]
ergibt einen Wert vom Typ IDictionary<TypeB, bool>
.
IDictionary<TypeB, bool>
entspricht nicht IDictionary<TypeA, bool>
, das sind völlig verschiedene und inkompatible Typen, daher der Compilerfehler.
Wenn Sie wollten Ihren Wörterbuch aus einer Sammlung von mehr abgeleiteten Typen auf diese Weise initialisieren, dann würden Sie die upcast explizit zu tun haben, zum Beispiel:
let iDict =
[ TypeB(), true; TypeB(), false ]
|> List.map (fun (a,b) -> (a :> TypeA), b)
|> dict
In Ihrem zweiten Beispiel dieser Das Problem trat nie auf, weil Sie ursprünglich eine Dictionary<TypeA, bool>
erstellt haben.
Verwenden Sie dann die Add
Methode, um etwas von TypeB
dem Wörterbuch hinzuzufügen. Da es sich bei Add
um eine Methode handelt, kann F # das automatische Upcasting für das Argument durchführen, sodass Ihr Wert von TypeB
automatisch auf TypeA
übertragen wird.
Gebunden, um ein Duplikat zu sein, aber Arrays in F # sind nicht kovariant - Methodenüberladungen wie add sind jedoch –
Weil 'KeyValuePair <'Key,' Value>' ist nicht kovariant auf ''Key'? – ildjarn
Interessant: [Eric Lipperts ehemaliger Blog - Stichwort: Kovarianz und Kontravarianz] (https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/) Hinweis: Die Liste ist in umgekehrter chronologischer Reihenfolge, Also fang am Ende an und arbeite weiter. –