2013-08-22 71 views
2

最近我遇到了C#泛型类型继承的一个有趣的行为。想象一下下面的例子:在C#中打开泛型继承的其他类型#

class Foo<T> {} 

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

当我们用封闭式泛型类型,其继承权的行为是很明显的:

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

但是,当我们使用开放式泛型类型,我们得到如下:

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

就我个人而言,我预计此行打印出True。那么,让我们来看看基本类型的Bar<>:这是从创建

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: 

所以在这里我们有一个类型(第一个):上述

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); 

的线条产生下面的输出Foo<T>(第二个)替换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<string>而不是Foo<> ...那么为什么你会期望它不同,只是因为它使用类型参数而不是具体类型?

+0

乔恩,谢谢你的解释,现在我明白了。我只是期望'X2','X3','X4'的泛型定义的基类是'Foo <>'。但是现在看来很清楚,这个基类需要将类型参数从'Bar '传递到'Foo '。 – takemyoxygen