Generic Covariance & Contra-variance는 C # 4.0에서 어떻게 구현됩니까?


106

PDC 2008에는 참석하지 않았지만 C # 4.0이 Generic covariance와 contra-variance를 지원하기 위해 발표되었다는 소식을 들었습니다. 즉,에 List<string>할당 할 수 있습니다 List<object>. 어떻게 그럴 수 있습니까?

Jon Skeet의 저서 C # in Depth 에서는 C # 제네릭이 공분산 및 반 분산을 지원하지 않는 이유를 설명합니다. 주로 보안 코드를 작성하기위한 것입니다. 이제 C # 4.0이이를 지원하도록 변경되었습니다. 혼란을 가져올까요?

C # 4.0에 대한 세부 정보를 아는 사람이 몇 가지 설명을 제공 할 수 있습니까?


다음은 C # 4.0의 대리자 및 인터페이스에 대한 향후 공분산 및 반 분산 구현을 다루는 좋은 기사입니다. LINQ Farm : C # 4.0의 공분산 및 공분산
CMS

Anders Noråse는 C # 4.0-공분산 및 반 분산 개념을 설명하고 .NET 2.0 이후 IL에서 이미 지원되고 있음을 보여줍니다.
Thomas Freudenberg

답변:


155

Variance는 실제로 CLR이 이미 가지고있는 기능을 사용하여 안전한 방식으로 만 지원됩니다 . 그래서 내가 List<Banana>a를 List<Fruit>(또는 그것이 무엇이든) 사용하려는 책에서 제공하는 예제 는 여전히 작동하지 않을 것입니다. 그러나 몇 가지 다른 시나리오는 작동합니다.

첫째, 인터페이스와 델리게이트에 대해서만 지원됩니다.

둘째, 인터페이스 / 대리자의 작성자가 유형 매개 변수를 in(반 변성의 경우) 또는 out(공분산의 경우) 로 장식해야합니다 . 가장 명백한 예는 IEnumerable<T>값을 "밖으로"가져 오도록 허용하는 것입니다. 새 값을 추가 할 수는 없습니다. 그것은 될 것 IEnumerable<out T>입니다. 이것은 타입 안전성을 전혀 손상시키지 않지만 예를 들어 IEnumerable<string>반환 IEnumerable<object>하도록 선언 된 메서드에서 를 반환 할 수 있습니다 .

Contravariance는 인터페이스 사용에 대한 구체적인 예를 제공하기가 더 어렵지만 델리게이트를 사용하면 쉽습니다. 고려하십시오 Action<T>- T매개 변수 를 취하는 메소드를 나타냅니다 . 완벽하게 변환 사용할 수 있도록 좋을 것이다 Action<object>AS를 Action<string>소요 어떤 방법 - object매개 변수는이되게 때 벌금을 될 것입니다 string대신합니다. 물론 C # 2에는 이미 어느 정도 대리자의 공분산 및 반공 변성이 있지만 한 대리자 형식에서 다른 대리자 형식으로의 실제 변환 (새 인스턴스 만들기)을 통해 예를 들어 P141-144를 참조하십시오. C # 4는 이것을 더 일반적으로 만들고 (내 생각에) 변환을위한 새 인스턴스를 만들지 않을 것입니다. (대신 참조 변환이됩니다.)

이로 인해 문제가 해결되기를 바랍니다. 이해가되지 않으면 알려주세요!


3
그렇다면 클래스가 "List <out T>"로 선언되면 "void Add (T obj)"와 같은 멤버 함수가 없어야한다는 의미입니까? C # 4.0 컴파일러는 이에 대한 오류를보고합니다.
Morgan Cheng

1
모건 : 확실히 제 이해입니다.
Jon Skeet

4
여기에 대한 귀하의 답변 중 하나가 즉시 일부 코드를 개선하는 데 도움이되었습니다. 감사합니다!
Mark

@ Ark-kun : 네, 알고 있습니다. 따라서 같은 문장에서 "여전히 작동하지 않을 것입니다". (그리고 나도 이유를 알고 있어요.)
존 소총

@JonSkeet는 그 "당신은 단지를 사용할 수있는 올바른 List<Banana>int로서 IList<Fruit>방주 군 @로는"? 그렇다면 IList<T>인터페이스 의 유형 매개 변수가 공변으로 정의되지 out T않았지만 (아니요 , 단순히 T) 어떻게 가능합니다 .
gehho

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.