将类从asType转换为类 :无法施放

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

我试图将asType()的对象转换为它的父类。

这是我的结构(我认为不需要细节,只是类描述和继承)

    public class Entity1: Entity
    {}
    public class Entity2: Entity
    {}
public class Entity
    {}

public class ClassM1 : MigrationBaseReverse<Entity1, Entity2>
    {}

public class MigrationBaseReverse<T, M> : MigrationBase<T, M>
        where T : Entity, new()
        where M : Entity, new()  
    {}

 public class MigrationBase<T, M>
        where M : Entity, new()
        where T : Entity, new()
    {}

我所做的 :

我像这样存储了ClassM1的类型信息(ti是一个TypeInfo):

Type type = ti.AsType();

然后,我用Activator创建一个新实例

instance = Activator.CreateInstance(type);

然后我(或者直接在Activator中,但得到相同的结果),尝试将它像它的父母一样投射

instance as MigrationBase<Entity, Entity>

但这不起作用,我得到了null,而这显然有效

instance as MigrationBase<Entity1, Entity2>

由于Entity1和Entity2继承自实体,我认为我可以使用Entity,但似乎不是。

我也试过像这样的演员:

(MigrationBase<Entity1, Entity2>) instance 

但我在演员阵容中遇到如下错误:

Unable to cast object of type 'ClassM1' to type 'MigrationBase`2[Entity,Entity]'.

我应该补充一点,我尝试使用MigrationBaseReverse进行所有这些转换

任何想法,将不胜感激。

我不确定标题,因为解释起来很复杂,所以如果一个人知道一个更好的标题,那就不要害怕编辑。

我希望你能得到你需要的所有信息。

c# casting
1个回答
4
投票

这个问题每周在SO上被问到1000次。

首先,c#中的泛型类型差异仅允许在接口和委托上使用。你没有。

其次,为了允许类型差异,您必须证明它是安全的。 IList<string>不是IList<object>,因为转换只是不安全; IList<T>T中是不变的。

IEnumerable<string>IEnumerable<object>,因为IEnumerable<out T>T中是协变的。

使用您提供的代码,无法确定理论上的IMigrationBase<T, M>是否可以在TM中协变。如果可以,那么您的转换将起作用,如果不能,则不会。

关于这个主题的一个非常有用的读物​​:Covariance and Contravariance in C# series。一定要阅读第六部分。

更新:

好吧,想象你的理论IMigrationBase<T, M>看起来像这样:

interface IMigrationBase<T, M>
    where T: Entity
    where M: Entity
{
    M Migrate(T entity) { .... }
}

想象一下这是合法的:

var m1 = new ClassM1();
IMigrationBase<Entity, Entity> m = m1; //illegal but lets play along

然后我们可能有以下可怕的想法:

m.Migrate(new Entity3()); //Legal but ouch!

而现在m,真的是m1,突然试图迁移一个它一无所知的Entity3类型。发生这种情况是因为T中的界面不协变(M中的协变性,而T中的反变量),转换永远不会安全。如果你想要类型方差,这个理论界面的真正声明将是IMigrationBase<in T, out M>,以下转换将是安全的:

IMigrationBase<Entity1, Entity> m = m1;

如果您的界面在TM中是协变的,那么您尝试的转换将是安全的。你怎么知道它在TM的协变性?好吧,拇指的规则(不是100%准确,但大部分时间都足够好),TM应该只是接口成员的输出(out),从不输入(in)。如果您的接口需要使用其通用类型之一作为输入,那么它在泛型类型参数中永远不会是协变的。

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