如何将List <t>转换为我自己的Collection

时间:2018-04-12 19:06:23

标签: c# .net generic-collections

由于各种原因,我已经实现了自己的集合类。 如何避免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
{
}

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

我也知道我可以做list.ForEach(resultCollection.Add);。但这意味着要重复迭代这个我想避免的收藏。

3 个答案:

答案 0 :(得分:3)

只需更改构造函数,以便可以使用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时,它才会迭代您的集合。

答案 1 :(得分:1)

增加已经很好的答案。你问:

  

我是否继承了List,所以我不能投出?

是和否。

您的特定强制转换在编译时工作,但不在运行时工作。

Casting是告诉编译器的一种方式,&#34;相信我。这将在运行时工作。&#34;

在运行时,只有当Base内的基础对象实际上是Descendant类型的对象时,我们才能从Base类转换为Descendant类。 / p>

例如,请记住string来自object,这里说明了您的演员在运行时失败的原因。

// 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;

答案 2 :(得分:0)

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