将通用列表转换为从列表派生的类

时间:2010-07-04 16:11:50

标签: c#

我创建了一个派生自List的类。但是,当我尝试将类转换为另一个List对象时,我收到运行时错误。我的代码类似于下面发布的代码:

public class CategoryObj
{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
    public string Description { get; set; }
}

public class CategoryObjCollection:List<CategoryObj>
{

}

public void Test()
{
        CategoryObjCollection cat = new CategoryObjCollection();
        using (NWDataContext db = new NWDataContext())
        {
            var qry = (from c in db.Categories
                       select new CategoryObj
                       {
                           CategoryID = c.CategoryID,
                           CategoryName = c.CategoryName,
                           Description = c.Description
                       }).ToList();
            cat = (CategoryObjCollection)qry; //runtime error Unable to cast object of type 'System.Collections.Generic.List`1[WindowsFormsApplication1.CategoryObj]' to type 'WindowsFormsApplication1.CategoryObjCollection'.
        }
}

我希望有人可以帮助我。感谢。

5 个答案:

答案 0 :(得分:12)

为什么你期望能够演员?对象不是 CategoryObjCollection的实例。引用类型转换(当它们实际转换而不是调用显式转换时)是告诉编译器您认为对象的执行时间类型实际上与您指定的类型兼容,这样您就可以使用该特定类型的成员(在执行时间测试之后)。在这种情况下,ToList扩展方法只会创建一个新的List<T>

更重要的是,您的CategoryObjCollection类型首先要实现的目标是什么?如果它具有除正常列表之外的任何状态,那么在LINQ查询之后,您希望该状态来自何处?如果它没有任何其他状态,它真的会增加任何好处吗?也许你的类型应该包含列表而不是从中派生?然后,您可以使用查询结果创建该类型的新实例。

一般来说,它通常是源于List<T>的设计气味。它并没有提供很多方法来专门化它的“列表”(不像,Collection<T>)。这通常表明你应该考虑构图而不是继承。

答案 1 :(得分:6)

试试这个

public class CategoryObjCollection:List<CategoryObj>
{
   public CategoryObjCollection(IEnumerable<CategoryObj> items) : base(items){}
}


cat = new CategoryObjCollection(qry);

答案 2 :(得分:3)

只有在您实施了转换运算符后才能使用强制转换。但这不是一种非常有效的方法。

您是否尝试创建类型别名(如C ++ typedef)?

using CategoryObjCollection = System.Collections.Generic.List<myNamespace.CategoryObj>;

现在,您可以在CategoryObjCollectionList<CategoryObj>之间自由转换(这是相同的类型 - 仅以不同的名称命名。

我还会使用不同的方法来填充列表:

db.Categories.ForEach(c =>
    cat.Add(new CategoryObj()
        {
            CategoryID = c.CategoryID,
            CategoryName = c.CategoryName,
            Description = c.Description
        }));

答案 3 :(得分:0)

你为什么要施展?你实际上不应该投射....只需在qry上添加一个循环并填写你的cat列表。

答案 4 :(得分:0)

您可以使用此扩展方法

public static M Cast<T, M>(this IEnumerable<T> input) where M : ICollection<T>, new()
{
  var ret = new M();
  foreach(var item in input?? Enumerable.Empty<T>())
  {
    ret.Add(item);
  }
  return ret;
}

然后您可以像使用它

var qry = (from c in db.Categories
   select new CategoryObj
   {
       CategoryID = c.CategoryID,
       CategoryName = c.CategoryName,
       Description = c.Description
    }).Cast<CategoryObj,CategoryObjCollection>()