2

最近我遇到了一个有趣的 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>(第二个)通过替换TT(不寻常的,但有效的,因为T也是运行时生成的类型)创建的。如果我们有另一个继承自 的Foo<T>类型,则将生成新的基类型:

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

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

所以,我的问题是:为什么我们需要在Bar<>andFoo<>和之间的这些“代理”类型Another<>and Foo<>,为什么开放的泛型类型不能相互继承?

4

1 回答 1

3

如果你给这两个类型参数不同的名字 -例如,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具有指定的类型参数 *by 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<>......那么为什么你会因为它使用类型参数而不是具体类型而期望它有所不同呢?

于 2013-08-22T06:40:33.037 回答