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

관심 분야 : [Eric Lippert의 Erstwhile Blog - 키워드 : 공분산 및 Contravariance] (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)입니다.

따라서 IDictionary<TypeB, bool> 유형의 값의 함수를 dict

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

결과를 적용.

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에 자동으로 업 캐스트합니다.

관련 문제