IT TIP

공분산과 업 캐스팅의 차이점

itqueen 2020. 12. 4. 21:36
반응형

공분산과 업 캐스팅의 차이점


공분산과 업 캐스팅의 차이점은 무엇입니까? 더 구체적으로는 왜 서로 다른 이름이 지정됩니까?

'업 캐스트'라고하는 다음 예를 보았습니다.

string s = "hello";
object o = s;  //upcast to 'string' to 'object'

반면에 다음은 '공분산'이라고합니다.

string[] s = new string[100];
object[] o = s;

IEnumerable<string> ies = new List<string>();
IEnumerable<object> ieo = ies;

이제 훈련되지 않은 내 눈에 공분산은 컬렉션의 캐스팅을 참조한다는 점을 제외하면 업 캐스팅과 동일하게 보입니다. (그리고 반 변성 및 다운 캐스팅과 관련하여 유사한 진술을 할 수 있습니다).

정말 그렇게 간단합니까?


이제 훈련되지 않은 내 눈에 공분산은 컬렉션의 캐스팅을 참조한다는 점을 제외하면 업 캐스팅과 동일하게 보입니다. (그리고 반 변성 및 다운 캐스팅과 관련하여 유사한 진술을 할 수 있습니다).

정말 그렇게 간단합니까?

공분산은 업 캐스팅에 관한 것이 아니지만, 왜 관련이 있다고 생각하는지 알 수 있습니다.

공분산은 다음과 같은 매우 간단한 아이디어에 관한 것입니다. derivedSequence유형 의 변수가 있다고 가정 해 봅시다 IEnumerable<Derived>. baseSequence유형 의 변수가 있다고 가정 해 봅시다 IEnumerable<Base>. 여기 Derived에서 Base. 그런 다음 공분산을 사용하면 다음이 법적 할당이며 암시 적 참조 변환이 발생합니다.

baseSequence = derivedSequence;

이것은 업 캐스팅이 아닙니다. IEnumerable<Derived>에서 파생되는 것은 아닙니다 IEnumerable<Base>. 오히려 변수 값을 변수 derivedSequence할당 할 수있는 것은 공분산입니다 baseSequence. 아이디어는 유형의 변수가 유형의 Base객체에서 할당 될 수 있으며 매개 변수가 공변 Derived이기 때문에 IEnumerable<T>유형의 객체를 유형의 IEnumerable<Derived>변수에 할당 할 수 있다는 것 IEnumerable<Base>입니다.

물론 저는 아직 공분산이 무엇인지 실제로 설명하지 않았습니다. 일반적으로 공분산은 다음과 같은 간단한 아이디어에 관한 것입니다. 하자 당신은 매핑이 있다고 F유형 유형의 (I에 의해이 매핑을 나타내는 것이다 F<T>; 유형 주어진 T매핑 아래의 이미지 F입니다 F<T>.)이 매핑은 다음과 같은 매우 특별한 속성을 가지고하자 말을 :

경우 X와 호환 과제는 Y다음 F<X>과 호환 과제입니다 F<Y>뿐만 아니라이.

이 경우 F매개 변수에서 공변 이라고합니다 T. (여기서 " Ais assignment compatible with B"where Aand Bare reference types는의 인스턴스 B가 유형의 변수에 저장 될 수 있음을 의미합니다 A.)

우리의 경우에는, IEnumerable<T>C # 4.0의 경우에서 암시 기준 환산 IEnumerable<Derived>하는 IEnumerable<Base>경우 Derived로부터 유도된다 Base. 할당 호환성의 방향은 유지되며 이것이 IEnumerable<T>유형 매개 변수에서 공변 이라고 말하는 이유 입니다.


캐스팅객체와 표현식 의 정적 유형을 변경하는 것을 말합니다 .

분산특정 상황 (예 : 매개 변수, 제네릭 및 반환 유형)에서 유형상호 교환 가능성 또는 동등성을 나타냅니다 .


IEnumerable<string>은에서 파생되지 않으므로 IEnumerable<object>그들 사이의 캐스트는 업 캐스트가 아닙니다. IEnumerable은 형식 매개 변수가 공변하고 문자열 개체에서 파생되므로 캐스트가 허용됩니다.


개념이 다른 이유는 업 캐스팅과 달리 공분산이 항상 허용되는 것은 아니기 때문입니다. 유형 시스템의 설계자가에서 "파생 된"IList<Cat> 것으로 간주되는 것은 쉬웠을 것 입니다 . 그러나 문제가 발생합니다.IList<Animal>

IList<Cat> cats = new List<Cat>();
IList<Animal> animals = cats; 
animals.Add(new Dog()); //Uh oh!

이것이 허용 되었다면 이제 우리 cats목록에는 Dog!

반대로 IEnumerable<T>인터페이스에는 요소를 추가 할 방법이 없으므로 이것은 완벽하게 유효합니다 (C # 4.0에서).

IList<Cat> cats = new List<Cat>();
IEnumerable<Animal> animals = cats;
//There's no way to add things to an IEnumerable<Animal>, so here we are ok

아래의 블로그 게시물에는 이에 대한 좋은 설명이 있습니다.

http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx


공분산을 수집 할 수있는 것에서 이전 업 캐스트 이후에 명시적인 다운 캐스트가 필요하지 않습니다. 일반적으로 객체를 업 캐스트하는 경우 기본 유형 메서드 및 특성에만 액세스 할 수 있으며, 공분산을 사용하면 더 많은 파생 클래스 선언에서 더 적은 파생 유형을 더 많은 파생 유형으로 대체하여 다운 캐스트를 암시 할 수 있습니다.

참고 URL : https://stackoverflow.com/questions/6707619/difference-between-covariance-and-upcasting

반응형