我有一个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>?
答案 0 :(得分: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?!
这就是为什么泛型类必须完全匹配的原因。可以使用更多的专业输入,因为它们可以自动 up 被投射为适当的类型。但是,不是更专业的输出-您不能粗心地 down 广播,这就是上面(假设)代码中发生的情况。在具有不同上下行语法的语言中,例如C ++的static_cast
和dynamic_cast
以及F#的:>
和:?>
,这是显而易见的。
输入和输出类型之间的这种区分实际上很重要,并且在C#中形式化为in
和out
通用参数,对应于协方差和相反方差的概念。不过,这仅适用于接口。
鉴于通用参数的多态行为在逻辑上是不可能的,因此您可能在设计中犯了一个细微的错误,即使您重构为使用接口也可能会遇到这种错误。仔细分析您的设计,并将多态逻辑从泛型中移开。您可以使用反射来解决此限制,但是除非您有非常充分的理由,否则您不应该这样做。