c# - C# 中开放泛型类型继承中的附加类型

标签 c# .net generics inheritance

最近我发现了 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<> 之间的这些“代理”类型和Foo<>Another<> 之间和Foo<> ,为什么开放泛型类型不能互相继承?

最佳答案

如果为两个类型参数指定不同的名称会更清楚 - 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<> ...那么为什么您会期望它有所不同,仅仅因为它使用类型参数而不是具体类型?

关于c# - C# 中开放泛型类型继承中的附加类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18373179/

相关文章:

java - 是否有一些轻量级技术可以为标识符属性添加类型安全?

c# - 我怎样才能把这个类写得完全通用,并根据一个请求返回不同的响应?

java - 为什么我不能分配给这个通用变量?

c# - LINQ-to-SQL .ExecuteCommand() 不适用于参数化对象名称

c# - 为什么我的 ASP.NET Core 2 方法不能返回 TwiML?

c# - iTextSharp 有效许可证不起作用

.net - 在 Application_Startup 中显示窗口。 WPF

c# - AWS Cognito 内置登录重定向问题

c# - 是否有HTML的#Region代码

.net - 我是否应该提供在最新框架版本中构建的程序集,即使我没有使用它的任何功能?