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

问题描述 投票:0回答:1

我有一个继承自模板类的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>?

c# templates inheritance
1个回答
0
投票

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

假设我们有:

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通用参数,对应于协方差和逆变的概念。这仅适用于接口。

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

© www.soinside.com 2019 - 2024. All rights reserved.