最近我发现了 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<>
的基类型:
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:
所以这里我们有一个从 Foo<T>
创建的类型(第一个) (第二个)替换 T
与 T
(不寻常,但有效,因为 T
也是运行时生成的类型)。如果我们有另一个继承自 Foo<T>
的类型,然后将生成新的基类型:
class Another<T> : Foo<T> { }
Console.WriteLine(typeof(Another<>).BaseType == typeof(Bar<>).BaseType); // False
所以,我的问题是:为什么我们需要 Bar<>
之间的这些“代理”类型和Foo<>
和 Another<>
之间和Foo<>
,为什么开放泛型类型不能互相继承?
最佳答案
如果为两个类型参数指定不同的名称会更清楚 - T1
和T2
, 例如。那么差异就变得更明显了:
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<>
...那么为什么您会期望它有所不同,仅仅因为它使用类型参数而不是具体类型?
关于c# - C# 中开放泛型类型继承中的附加类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18373179/