2016-07-17 9 views
3
type TypeA() = class end 
type TypeB() = inherit TypeA() 

// "The type 'TypeA' does not match the type 'TypeB'": 
let iDict : IDictionary<TypeA, bool> = [ TypeB(), true; TypeB(), false ] |> dict 

let d = Dictionary<TypeA, bool>() 
// This is OK, though: 
d.Add (TypeB(), false) 

Warum sind IDictionary-Schlüssel mit abgeleiteten Typen inkompatibel?Warum sind IDictionary <_, > Schlüssel nicht mit abgeleiteten Typen kompatibel?

+4

Gebunden, um ein Duplikat zu sein, aber Arrays in F # sind nicht kovariant - Methodenüberladungen wie add sind jedoch –

+3

Weil 'KeyValuePair <'Key,' Value>' ist nicht kovariant auf ''Key'? – ildjarn

+0

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. –

Antwort

2

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.

Verwandte Themen