I've got a problem that I can work around, but I feel like there should be a solution within Linq that I'm just not seeing.
So I have two classes, a detail record class and a collection of those classes:
public class ItemDetail
{
public string Name {get;set;}
public int? Id {get;set;}
}
public class ItemDetailCollection : List<ItemDetail>
{
}
Now, I can fill up those objects using my repository layer without a problem, and query the data to get the subset of records I want.
var items = Repository.GetItemCollection();
var reportItemCollection = items.Where(x=>x.Id.HasValue);
This is all fine and dandy. However, the reportItemCollection
is an IEnumberable<ItemDetail>
, and what I really want is a new ItemDetailCollection
.
Of course, I could create a new collection and add the query range, but I feel like there is a way to automatically populate the result set as the specific collection type. I've tried adding the following and only receive the results as NULL
:
var reportItemCollection = items.Where(x=>x.Id.HasValue) as ItemDetailCollection;
And trying .Cast<ItemDetailCollection>()
does not work either. Finally, I've tried
var reportItemCollection = items.Where(x=>x.Id.HasValue).Select(result => new ItemDetailCollection(){ result });
but this only gives me an IEnumerable<ItemDetailCollection>
.
Any thoughts?
The only way is to actually construct the collection, using the constructor for List<T>
:
public class ItemDetailCollection : List<ItemDetail>
{
public ItemDetailCollection(IEnumerable<ItemDetail> items)
: base(items) { }
}
And
var reportItemCollection = new ItemDetailCollection(
items.Where(x=>x.Id.HasValue)
);
You can't cast an IEnumerable<T>
to a subclass like ItemDetailCollection
, due to the rules of covariance/contravariance (see here, for example: http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx).
I would solve this the same way that LINQ solves it for List<T>
: create a ToItemDetailCollection
extension method
static ItemDataCollection ToItemDataCollection(this IEnumerable<ItemDetail> e) {
return new ItemDataCollection(e);
}
Then you can just append this to any query
var reportItemCollection = items
.Where(x=>x.Id.HasValue)
.ToItemDataCollection();
On a separate note I would question why you are deriving from List<T>
at all. It offers no virtual
methods to override and hence there is no possibility of customization. Using this over List<ItemDetail>
everywhere will just cause a lot of pain points like this one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With