繁体   English   中英

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

[英]Casting of Generic List to a Class derived from a List

我创建了一个派生自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'.
        }
}

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

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

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

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

试试这个

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


cat = new CategoryObjCollection(qry);

只有在您实现转换运算符后,转换才会起作用。 但这不是一种非常有效的方法。

您是否尝试创建类型别名(如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
        }));

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

您可以使用此扩展方法

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>()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM