공분산과 업 캐스팅의 차이점
공분산과 업 캐스팅의 차이점은 무엇입니까? 더 구체적으로는 왜 서로 다른 이름이 지정됩니까?
'업 캐스트'라고하는 다음 예를 보았습니다.
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
. (여기서 " A
is assignment compatible with B
"where A
and B
are 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
'IT TIP' 카테고리의 다른 글
HTTP 응답을 보낸 후 계속 PHP 실행 (0) | 2020.12.04 |
---|---|
DRY way to add created/modified by and time (0) | 2020.12.04 |
C에서 stdin 및 stdout 경로 변경 (0) | 2020.12.03 |
IIS7에서 net.tcp 활성화 (0) | 2020.12.03 |
jQuery UI datepicker를 * 완전히 * 제거하려면 어떻게합니까? (0) | 2020.12.03 |