如何将 List<T> 投射到我自己的 Collection
How to Cast List<T> to my own Collection
出于各种原因,我实现了自己的 collection class。
如何避免在 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);
。但这意味着我想避免再次迭代 collection。
只需更改您的构造函数,以便您可以使用 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
时迭代您的集合一次。
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);
增加已经很好的答案。你问:
I'm inheriting from List so shouldn't I be able to cast?
是也不是。
您的特定转换在编译时有效,但在运行时无效。
转换是一种告诉编译器的方式,"Trust me. This will work at runtime."
在运行时,只有当 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;
出于各种原因,我实现了自己的 collection class。
如何避免在 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);
。但这意味着我想避免再次迭代 collection。
只需更改您的构造函数,以便您可以使用 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
时迭代您的集合一次。
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);
增加已经很好的答案。你问:
I'm inheriting from List so shouldn't I be able to cast?
是也不是。
您的特定转换在编译时有效,但在运行时无效。
转换是一种告诉编译器的方式,"Trust me. This will work at runtime."
在运行时,只有当 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;