[英]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
类。
例如,请记住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;
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.