2013-08-22 1 views
2

최근에 나는 C# 제네릭 형식 상속의 흥미로운 동작을 발견했습니다.C#의 공개 제네릭 형식 상속 유형 추가

Console.WriteLine(typeof(Bar<int>).BaseType == typeof(Foo<int>)); // True 

그러나 우리는 열린 제네릭 형식을 사용할 때, 우리는 다음을 얻을 :

class Foo<T> {} 

class Bar<T> : Foo<T> {} 

우리가 폐쇄 일반적인 유형을 사용, 상속의 관점에서 그들의 행동은 매우 분명하다 :

를 다음과 같은 예를 생각해
Console.WriteLine(typeof(Bar<>).BaseType == typeof(Foo<>)); // False 

개인적으로 나는이 줄이 True 인 것을 인쇄 할 것을 기대했습니다.

Action<Type> discoverType = type => 
    { 
     Console.WriteLine("Type name: " + type.ToString()); 

     Console.WriteLine("Is generic type definition: " + 
      type.IsGenericTypeDefinition); 

     Console.WriteLine("Generic ags: " + 
      string.Join<Type>(", ", type.GetGenericArguments())); 

     Console.WriteLine("Types in generic:" + 
      string.Join<Type>(", ", type.GenericTypeArguments)); 

     Console.WriteLine(Environment.NewLine); 
    }; 

Type baseType = typeof(Bar<>).BaseType; 
discoverType(baseType); 

Type openType = baseType.GetGenericTypeDefinition(); 
discoverType(openType); 

의 선 위의 다음과 같은 출력 생성 : 우리는 유형 (첫 번째)가 그래서 여기

Type name: GenericsReflection.Program+Foo`1[T] 
Is generic type definition: False 
Generic ags: T 
Types in generic:T 


Type name: GenericsReflection.Program+Foo`1[T] 
Is generic type definition: True 
Generic ags: T 
Types in generic: 

을에서 생성 된 자, Bar<>의 기본 유형을 살펴 보자 (두 번째 것)은 TT으로 바꿉니다 (이상하지만 올바르지 만 T은 런타임 생성 유형이기도 함). 우리가 Foo<T>에서 상속 다른 유형을 가지고 있다면, 새로운 기본 유형이 생성됩니다

class Another<T> : Foo<T> { } 

Console.WriteLine(typeof(Another<>).BaseType == typeof(Bar<>).BaseType); // False 

그래서, 내 질문은 왜 우리가 Bar<>Foo<> 사이 Another<>Foo<> 사이의 이러한 "프록시"유형을해야합니까, 열린 제네릭 형식을 서로 상속 할 수없는 이유는 무엇입니까?

답변

3

두 유형 매개 변수에 다른 이름 (예 : T1T2)을 지정하면 명확 해집니다. 그런 차이가 명확하게 : 그들은 정말 다른

Type name: Foo`1[T2] 
Is generic type definition: False 
Generic ags: T2 
Types in generic:T2 


Type name: Foo`1[T1] 
Is generic type definition: True 
Generic ags: T1 
Types in generic: 

-typeof(Bar<>).BaseType는) Bar<>에 의해 * 지정된 인수를 입력했다 - 당신이 Bar<> 자체는 구체적인 Foo<>를 얻을 수 있습니다 전에 구체적가 필요 단지입니다. 즉, typeof(Bar<>).BaseType이고, typeof(Foo<>) 유형입니다. 이에 대한 자세한 내용은 Type.IsConstructedGenericType을 참조하십시오 (두 가지 유형에 대해 다른 값을 제공하는 또 다른 속성입니다).

class X1 : Foo<string> {} 
class X2<T> : Foo<string> {} 
class X3<TKey, TValue> : Foo<TKey> {} 
class X4<TKey, TValue> : Foo<TValue> {} 

당신이 typeof(Foo<>)와 동일하게 해당 유형의 각각의 기본 유형을 기대 :

이 세 가지 선언을 고려, 그것을 다른 방법을 넣으려면? 첫 번째와 두 번째 경우에는 반드시 이 아닌 Foo<> ... 확실한 형식 대신 형식 매개 변수를 사용하기 때문에 왜 다른 것으로 생각하십니까?

+0

Jon, 설명 주셔서 감사합니다. 이제 알려 드리겠습니다. 방금'X2','X3','X4'의 일반적인 정의의 기본 클래스가'Foo <>'라고 기대했습니다. 하지만 이제는이 기본 클래스가'Bar '에서'Foo '으로 형식 인수를 전달해야한다는 것이 확실합니다. – takemyoxygen