C#에서 공변성(Covariance)과 반공변성(Contravariance)은 배열 형식, 대리자 형식 및 제네릭 형식
인수에 대한 암시적 참조 변환을 가능하게 합니다.
공변성(Covariance)은 할당 호환성을 유지하고 반공변성(Contravariance)은 할당 호환성을 유지하지
않습니다.
다음 코드에서는
할당 호환성, 공변성(Covariance) 및 반공변성(Contravariance) 간의 차이를 보여 줍니다.
// 할당 호환성
string str = "test";
// 더 파생된 유형의 개체가 덜 파생된 유형의 개체에 할당됩니다.
object obj = str;
// 공변성.
IEnumerable<string> strings = new List<string>();
// 더 파생된 형식 인수로 인스턴스화되는 개체
// 덜 파생된 형식 인수로 인스턴스화된 개체에 할당됩니다.
// 할당 호환성은 유지됩니다.
IEnumerable<object> objects = strings;
// 반공변성.
// 다음 메서드가 클래스에 있다고 가정합니다.
static void SetObject(object o) { }
Action<object> actObject = SetObject;
// 덜 파생된 형식 인수로 인스턴스화되는 개체
// 더 파생된 형식 인수로 인스턴스화된 개체에 할당됩니다.
// 할당 호환성이 역전되었습니다.
Action<string> actString = actObject;
| 의미 | |
|---|---|
| 공변성(covariant) | T’가 T의 서브타입이면, C<T’>는 C<? extends T>의 서브타입이다. |
| 반공변성(contravariant) | T’가 T의 서브타입이면, C<T>는 C<? super T’>의 서브타입이다. |
| 무공변성(invariant) | C와 C<T’>는 아무 관계가 없다. |
변성이란 제너릭 프로그래밍을 하면서 상속에 관련되어 생기는 이슈가 생길때 접하곤합니다.
변성에 대해서 간단한 예시를 통해서 설명을 하자면 아래와 같이 쉽게 설명이 가능합니다.
Integer는 Number를 상속받아 만들어진 객체입니다.
그래서 Integer는 Number의 하위 타입이라고 할 수 있어 아래와 같은 코딩이 가능합니다.
public void test()
{
List<Number> list;
list.add(Integer.valueOf(1));
}