방프리
21.03.07 Chapter3. 제네릭 활용 (Item 22) 본문
Item 22 : 공변성과 반공변성을 지원하라
- 공변성과 반공변성은 무엇일까? 단어부터 생소하다. 타입의 가변성으로도 말하는데 특정 타입의 객체를 다른 타입의 객체로 변환할 수 있는 성격을 말한다.
abctract public class CelestialBody : IComparable<CelestialBody>
{
public double Mass { get; set; }
public string Name { get; set; }
}
public class Planet : CelestialBody
{
}
public class Moon : CelestialBody
{
}
public class Asteroid : CelestialBody
{
}
[예제에 사용될 클래스들]
- 공변성
- X를 Y로 바꾸어 사용할 수 있는 경우, C<X>를 C<Y>로도 바꾸어 사용할 수 있다면 C<T>는 공변이다.
- 출력위치에서만 사용되는데 이 때 출력위치는 함수의 반환값, 속성의 get 접근자, 델리게이트의 일부 위치이다.
- IEnumerator<T>를 정의할 때 T에 대해 out 데코레이터가 사용됨 (하단의 코드 참조)
public interface IEnumerable<out T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
public interface IEnumerator<out T> : IDisposable, IEnumerator
{
new T Current { get; }
}
공변성의 예
public static void CoVariantArray(CelestialBody[] baseItems)
{
foreach (var thing in baseItems)
{
Console.WriteLine($"{this.Name} has a mass of {thing.Mass} Kg");
}
//반환되는 타입이 정확하므로 에러를 발생하지 않는다.
}
public static void UnsafeVariantArray(CelestialBody[] baseItems)
{
baseItems[0] = new Asteroid
{ Name = "Hygiea", Mass = 8.85e19 };
//자식 클래스여도 타입이 다르기 때문에 예외를 일으킨다.
CelestialBody[] spaceJunk = new Asteroid[5];
spaceJunk[0] = new Planet();
//마찬가지로 타입이 다르기 때문에 예외가 발생
}
- 반공변성
- Y를 X로 바꾸어 사용할 수 잇는 경우 C<X>를 C<Y>로 바꾸어 사용할 수 있다면 C<T>는 반공변이다.
- 입력위치에서만 사용되는데 이 때 입력위치는 함수의 매개변수, 속성의 set 접근자, 델리게이트의 일부 위치이다.
- IComparable<T> 인터페이스가 in 데코레이터를 사용 (하단의 코드 참조)
public interface IComparable<in T>
{
int CompareTo(T other);
}
- 델리게이트의 매개변수
- 델리게이트의 매개변수에 공변/반공변을 지정하는 것은 어려운 작업은 아니지만 사용시 인지 문제가 생길 수 있다. (반대로 쓸 가능성이 있음)
- 컴파일러 단에서 오류를 검출하고 싶다면 반드시 in, out 키워드를 적극 활용하자.
'C# > Effective C#' 카테고리의 다른 글
21.03.27 Chapter3. 제네릭 활용 (Item 24) (0) | 2021.03.27 |
---|---|
21.03.14 Chapter3. 제네릭 활용 (Item 23) (0) | 2021.03.14 |
21.02.07 Chapter3. 제네릭 활용 (Item 21) (0) | 2021.02.07 |
20.10.26 Chapter3. 제네릭 활용 (Item 20) (0) | 2020.10.26 |
20.10.22 Chapter3. 제네릭 활용 (Item 19) (0) | 2020.10.22 |
Comments