我遇到了一个我可以解决的问题,但我觉得Linq中应该有一个我没有看到的解决方案。
所以我有两个类,一个详细记录类和这些类的集合:
public class ItemDetail
{
public string Name {get;set;}
public int? Id {get;set;}
}
public class ItemDetailCollection : List<ItemDetail>
{
}
现在,我可以使用我的存储库层填充这些对象而没有问题,并查询数据以获取我想要的记录子集。
var items = Repository.GetItemCollection();
var reportItemCollection = items.Where(x=>x.Id.HasValue);
这一切都很好,花花公子。但是,reportItemCollection
是IEnumberable<ItemDetail>
,我真正想要的是新的ItemDetailCollection
。
当然,我可以创建一个新的集合并添加查询范围,但我觉得有一种方法可以自动将结果集填充为特定的集合类型。我尝试添加以下内容,只收到NULL
的结果:
var reportItemCollection = items.Where(x=>x.Id.HasValue) as ItemDetailCollection;
尝试.Cast<ItemDetailCollection>()
也不起作用。最后,我试过了
var reportItemCollection = items.Where(x=>x.Id.HasValue).Select(result => new ItemDetailCollection(){ result });
但这只给了我一个IEnumerable<ItemDetailCollection>
。
有什么想法吗?
答案 0 :(得分:9)
唯一的方法是使用List<T>
的构造函数实际构建集合:
public class ItemDetailCollection : List<ItemDetail>
{
public ItemDetailCollection(IEnumerable<ItemDetail> items)
: base(items) { }
}
和
var reportItemCollection = new ItemDetailCollection(
items.Where(x=>x.Id.HasValue)
);
由于协方差/逆变规则,您无法将IEnumerable<T>
强制转换为类似ItemDetailCollection
的子类(请参阅此处,例如:http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx)。
答案 1 :(得分:4)
我会像LINQ为List<T>
解决它一样解决这个问题:创建一个ToItemDetailCollection
扩展方法
static ItemDataCollection ToItemDataCollection(this IEnumerable<ItemDetail> e) {
return new ItemDataCollection(e);
}
然后你可以将它附加到任何查询
var reportItemCollection = items
.Where(x=>x.Id.HasValue)
.ToItemDataCollection();
另外,我会问你为什么要从List<T>
派生出来。它没有提供virtual
方法来覆盖,因此不可能进行自定义。在List<ItemDetail>
到处使用它只会引起很多像这样的痛点。