.NET Framework 4에는 여러 기존 제네릭 인터페이스에 대한 분산 지원이 도입되었습니다. 가변성 지원을 사용하면 이러한 인터페이스를 구현하는 클래스를 암시적으로 변환할 수 있습니다.
.NET Framework 4부터 다음 인터페이스는 변형입니다.
IEnumerable<T> (T는 공변성)
IEnumerator<T> (T는 공변성)
IQueryable<T> (T는 공변성)
IGrouping<TKey,TElement> (
TKey
및TElement
공변성)IComparer<T> (T는 반공변성)
IEqualityComparer<T> (T는 반공변성)
IComparable<T> (T는 반공변성)
.NET Framework 4.5부터 다음 인터페이스는 변형입니다.
IReadOnlyList<T> (T는 공변성)
IReadOnlyCollection<T> (T는 공변성)
공변성에서는 메서드가 인터페이스의 제네릭 형식 매개 변수에 정의된 것보다 더 파생된 반환 형식을 가질 수 있습니다. 공변성 기능을 설명하기 위해 다음과 같은 제네릭 인터페이스를 고려해 보세요: IEnumerable<Object>
와 IEnumerable<String>
.
IEnumerable<String>
인터페이스는 IEnumerable<Object>
인터페이스를 상속하지 않습니다. 그러나 String
형식이 Object
형식을 상속하며, 경우에 따라 이러한 인터페이스 간의 개체를 서로 할당해야 할 수도 있습니다. 이는 다음 코드 예제에 나와 있습니다.
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
이전 버전의 .NET Framework에서 이 코드는 C#에서 컴파일 오류를 발생시키고, 있는 경우 Option Strict
Visual Basic에서 컴파일 오류를 발생합니다. 그러나 이제 strings
인터페이스가 공변성이기 때문에, 이전 예제에서 objects
대신 IEnumerable<T>을 사용할 수 있습니다.
반공변성에서는 메서드가 인터페이스의 제네릭 매개 변수에 지정된 것보다 덜 파생된 인수 형식을 가질 수 있습니다. 반공변을 설명하기 위해, BaseComparer
클래스 인스턴스를 비교하는 BaseClass
클래스를 만들었다고 가정합니다.
BaseComparer
클래스가 IEqualityComparer<BaseClass>
인터페이스를 구현합니다. 이제 IEqualityComparer<T> 인터페이스가 반공변이므로, BaseComparer
를 사용하여 BaseClass
클래스를 상속받은 클래스의 인스턴스를 비교할 수 있습니다. 이는 다음 코드 예제에 나와 있습니다.
// Simple hierarchy of classes.
class BaseClass { }
class DerivedClass : BaseClass { }
// Comparer class.
class BaseComparer : IEqualityComparer<BaseClass>
{
public int GetHashCode(BaseClass baseInstance)
{
return baseInstance.GetHashCode();
}
public bool Equals(BaseClass x, BaseClass y)
{
return x == y;
}
}
class Program
{
static void Test()
{
IEqualityComparer<BaseClass> baseComparer = new BaseComparer();
// Implicit conversion of IEqualityComparer<BaseClass> to
// IEqualityComparer<DerivedClass>.
IEqualityComparer<DerivedClass> childComparer = baseComparer;
}
}
자세한 예제는 제네릭 컬렉션에 대한 인터페이스에서 분산 사용(C#)을 참조하세요.
제네릭 인터페이스의 분산은 참조 형식에 대해서만 지원됩니다. 값 형식은 분산을 지원하지 않습니다. 예를 들어 IEnumerable<int>
정수가 값 형식으로 IEnumerable<object>
표현되므로 암시적으로 변환할 수 없습니다.
IEnumerable<int> integers = new List<int>();
// The following statement generates a compiler error,
// because int is a value type.
// IEnumerable<Object> objects = integers;
또한 변형 인터페이스를 구현하는 클래스는 여전히 고정되어 있다는 점을 기억해야 합니다. 예를 들어, List<T>은 공변 인터페이스 IEnumerable<T>를 구현하지만, 암시적으로 List<String>
를 List<Object>
로 변환할 수는 없습니다. 다음 코드 예제에 설명되어 있습니다.
// The following line generates a compiler error
// because classes are invariant.
// List<Object> list = new List<String>();
// You can use the interface object instead.
IEnumerable<Object> listObjects = new List<String>();
참고하십시오
.NET