如何在C#中构建我的模板化继承类?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在C#中构建我的模板化继承类?相关的知识,希望对你有一定的参考价值。

我有一个继承自模板类的A类:M<C, D>和类C : T<D>执行A是类型M<C, D>但不是类型M<T<D>,D>我不明白为什么。有这种通信的方法吗?

我使用LTS Unity 2017.4。

public class ContentItemModule<C,D> where C : ContentItem<D> where D : A_Data { }

public class ImplementedContentItemModule : ContentItemModule<ImplementedContentItem , ImplementedData> { }
public class ContentItem<D> where D : A_Data { }

public class ImplementedContentItem : ContentItem<ImplementedData> { 

    ImplementedContentItemModule _contentItemModule;

    public void Init() {
         Console.Log(_contentItemModule is ImplementedContentItemModule); // print True
         Console.Log(_contentItemModule is ContentItemModule<ImplementedContentItem, ImplementedData>); // print True
         Console.Log(_contentItemModule is ContentItemModule<ContentItem<ImplementedData>, ImplementedData>); // print False, WHY ?
    }
}

我希望第三个日志返回True,但它返回False。

注意:对于一个ImplementedData,只有一个ImplementedContentItem。

是否存在可以帮助我(或其他方式)的关键字,或者无法知道我的_contentItemModule是否是ContentItemModule,ImplementedData>?

答案

问题是泛型不遵循与普通类相同的可赋值规则。对于可分配的泛型类,类型必须完全匹配。这是一个向您展示原因的示例:

假设我们有:

class A { }
class B: A { }

多态性说我们可以将B的实例分配给类型A的变量。这是因为B是A.现在考虑一个列表:

var a_s = new List<A>();
a_s.Add(new A());
var b_s = (List<B>)a_s;
var b = b_s[0]; // But b_s[0] is the same as a_s[0], which is an A instance, and A's can't be assigned to B's!! What happened?!

这就是泛型类必须完全匹配的原因。更专业的输入很好,因为它们可以自动转换为适当的类型。但是,更专业的输出不是 - 你不能随意贬低,这就是上面(假设)代码中发生的事情。这在具有不同向上和向下翻译语法的语言中很明显,例如C ++的static_castdynamic_cast以及F#的:>:?>

输入和输出类型之间的区别实际上很重要,并且在C#中形式化为inout通用参数,对应于协方差和逆变的概念。这仅适用于接口。

鉴于泛型参数的多态行为在逻辑上是不可能的,您可能在设计中犯了一个微妙的错误,即使您重构使用接口也会遇到它。仔细分析您的设计,并将多态逻辑从泛型中移开。你可以使用反射来解决这个限制,但你真的不应该,除非你有一个非常好的理由。

以上是关于如何在C#中构建我的模板化继承类?的主要内容,如果未能解决你的问题,请参考以下文章

C++:从模板参数继承类

构建模板化容器类

c++模板和继承

从模板化父类访问继承的变量[重复]

一起使用模板和继承时,不知道如何覆盖成员函数

C++模板类的继承