繁体   English   中英

如何投放清单 <T> 到我自己的收藏

[英]How to Cast List<T> to my own Collection

由于各种原因,我已经实现了自己的集合类。 如何避免在ItemCollection resultCollection = (ItemCollection)list;上强制转换失败ItemCollection resultCollection = (ItemCollection)list; 我是从List<T>继承的,所以我不能投射吗? 我可以修改BaseEntityCollection使其能够执行此操作吗?

static class Program
{
    static void Main()
    {
        ItemCollection collection = new ItemCollection();
        Item item = new Item();
        item.ID = 1;
        item.Name = "John";
        collection.Add(item);
        List<Item> list = collection.FindAll(x => x.ID == 1 && x.Name == "John");

        ItemCollection resultCollection = (ItemCollection)list; // It's breaking here
    }
}


public class ItemCollection : BaseEntityCollection<Item>
{
}

public class Item : BaseEntity
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public abstract class BaseEntityCollection<T> : List<T>, IEnumerable<T> where T : BaseEntity, new()
{
}

public abstract class BaseEntity
{
}

我知道我可以在ItemCollection上单独实现FindAll ,但是我想利用List<T>上所有可用的方法。

我也知道我可以做list.ForEach(resultCollection.Add); 但这意味着我要避免再次遍历该集合。

只需更改构造函数,以便您可以使用List<Item>集合对其进行初始化。 这使您可以使用另一个集合来初始化项目集合:

static class Program
{
    static void Main()
    {
        ItemCollection collection = new ItemCollection();
        Item item = new Item();
        item.ID = 1;
        item.Name = "John";
        collection.Add(item);
        List<Item> list = collection.FindAll(x => x.ID == 1 && x.Name == "John");

        ItemCollection resultCollection = new ItemCollection(list);
    }
}


public class ItemCollection : BaseEntityCollection<Item>
{
    //Allow default constructor
    public ItemCollection() { }

    //Construct with a list collection
    public ItemCollection(IEnumerable<Item> collection)
        : base(collection)
    {

    }
}

public class Item : BaseEntity
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public abstract class BaseEntityCollection<T> : List<T>, IEnumerable<T> where T : BaseEntity, new()
{
    //Still be able to create blank items
    public BaseEntityCollection() { }

    public BaseEntityCollection(IEnumerable<T> collection)
        : base(collection)
    {

    }
}

public abstract class BaseEntity
{
}

为了避免重复访问您的列表两次,我将更改以下内容:

List<Item> list = collection.FindAll(x => x.ID == 1 && x.Name == "John");

var list = collection.Where(x => x.ID == 1 && x.Name == "John");

它将延迟加载列表(以某种方式),但是当您从列表中创建新的ItemCollection时,它只会对您的集合进行一次迭代。

扩大已经很好的答案。 您询问:

我是从List继承过来的,所以我不应该投射吗?

是的,没有。

您的特定类型转换在编译时有效,但在运行时无效。

强制转换是一种告诉编译器“信任我。这将在运行时起作用”的方法。

在运行时,仅当Base内部的基础对象实际上是Descendant类型的对象时,才可以从Base类转换为Descendant类。

例如,请记住stringobject派生的,这说明了为什么强制转换在运行时失败。

// builds but fails at runtime
object o1 = new object();
string s1 = (string)o1;     

// builds and works at runtime
// because o2 is a string in object's clothing
object o2 = (object)"";
string s2 = (string)o2;
ItemCollection resultCollection = new ItemCollection();
resultCollection.AddRange(collection.Where(x => x.ID == 1 && x.Name == "John"));

如果碰巧您没有AddRange扩展方法,请使用它。

void AddRange<T>(this ItemCollection c, IEnumerable<T> items) => foreach(T i in items) c.Add(i);

暂无
暂无

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

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