铸造List <classa>的问题,其中ClassA:Generic <int32>到List <generic <int32>&gt; </generic <int32> </int32> </classa>

时间:2013-04-04 10:08:27

标签: c# generics covariance

我有下一个课程:

public class EntityBase<T>
{
    public T Id { get; set; }

}

它的实施者:

public class ClassA : EntityBase<Int32>
{
     ...
}

public class ClassB : EntityBase<Int64>
{
     ...
}

在不熟悉类的代码中 - ClassAClassB它只知道EntityBase&lt; ...&gt;的存在,我做了类似的事情:

     // Here for sure I get the list of `ClassA`
     object obj = GetSomeHowListOfClassA();
     List<EntityBase<Int32>> listOfEntityBases = (List<EntityBase<Int32>>)obj;

我收到错误:

Unable to cast object of type 'System.Collections.Generic.List`1[...ClassA]' to type 'System.Collections.Generic.List`1[...EntityBase`1[System.Int32]]'.

我这样修理:

var listOfEntityBases = new List<EntityBase<Int32>>(obj);

但我不喜欢这种方式,因为我正在创建新的List&lt;&gt;。有没有办法施展它? 任何进步都是如此。

2 个答案:

答案 0 :(得分:2)

你出于明确原因不能这样做。我们假设这行代码工作:

 List<EntityBase<Int32>> listOfEntityBases = (List<EntityBase<Int32>>)obj;

这意味着在该行之后您可以执行以下操作

listOfEntityBases.Add(new EntityBase<Int32>());

但实际上这一行同时会将EntityBase<Int32>对象添加到objList<ClassA> - 这绝对是 InvalidCast

因此,您无法在同一时间内将{strong>相同的变量声明为List<ClassA>List<EntityBase<Int32>>

虽然IEnumerable<T>很容易被允许,因为无法为此类收集添加新值。

这就是为什么他们在泛型声明中有inout

答案 1 :(得分:0)

你不能这样做,因为:

  • C#中的协方差不适用于类;
  • 接口IList<T>ICollection<T>不是协变的。

您可以在此处执行的唯一选项(制作列表副本除外)是IEnumerabe<T>的投射:

var listOfEntityBases = (IEnumerable<EntityBase<Int32>>)obj;