2016-07-17 2 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) 

Почему ключи IDictionary несовместимы с производными типами?Почему нет IDictionary <_, > ключей, совместимых с производными типами?

+4

Связано с дубликатом, но массивы в F # не ковариантны - методы перегрузки, такие как добавление, хотя –

+3

Потому что 'KeyValuePair <'Key,' Value>' не ковариантно на '' Key'? – ildjarn

+0

Интересует: [Erstwhile Блог Эрика Липперта - ключевое слово: ковариация и контравариантность] (https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/) Примечание: список находится в обратном хронологическом порядке, поэтому начинайте с конца и работайте вперед. –

ответ

2

Давайте посмотрим на различия между этими двумя подходами:

В первом случае, вы создаете список:

[ TypeB(), true; TypeB(), false ] 

Это имеет тип (TypeB * bool) list.

Функция dict имеет тип seq<'Key * 'Value> -> IDictionary<'Key,'Value> (requires equality).

Следовательно, применяя функцию dict

dict [ TypeB(), true; TypeB(), false ] 

приводит к значению типа IDictionary<TypeB, bool>.

IDictionary<TypeB, bool> не является эквивалентом IDictionary<TypeA, bool>, это совершенно разные и несовместимые типы, следовательно, ошибка компилятора.

Если вы хотите инициализировать ваш словарь из коллекции более производных типов в этом случае, вы должны сделать вентиляционный явно, например:

let iDict = 
    [ TypeB(), true; TypeB(), false ] 
    |> List.map (fun (a,b) -> (a :> TypeA), b) 
    |> dict 

В вашем втором примере проблема никогда не материализовалась, потому что вы изначально создали Dictionary<TypeA, bool>.

Затем вы используете способ Add, чтобы добавить что-то из TypeB в словарь. Так как метод Add - это метод, F # может выполнять автоматическое повышение по аргументу, так что ваше значение TypeB автоматически обновляется до TypeA.

Смежные вопросы