Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq with custom base collection

Tags:

c#

linq

I often find linq being problematic when working with custom collection object. They are often defened as

The base collection

abstract class BaseCollection<T> : List<T> { ... }

the collections is defined as

class PruductCollection : BaseCollection<Product> { ... }

Is there a better way to add results from a linq expession to this collection than addrange or concat?

var products = from p in HugeProductCollection
               where p.Vendor = currentVendor
               select p;
PruductCollection objVendorProducts = new PruductCollection();
objVendorProducts.AddRange(products);

It would be nice if the object returned form the linq query was of my custom collection type. As you seem to need to enumerate the collection two times to do this.

EDIT : After reading the answers i think the best solution is to implementa a ToProduct() extention. Wonder if the covariance/contravariance in c#4.0 will help solve these kinds of problems.

like image 832
AndreasN Avatar asked Dec 16 '08 12:12

AndreasN


2 Answers

The problem is that LINQ, through extension methods on IEnumerable<T>, knows how to build Arrays, Lists, and Dictionaries, it doesn't know how to build your custom collection. You could have your custom collection have a constructor that takes an IEnumerable<T> or you could write you. The former would allow you to use the LINQ result in your constructor directly, the latter would allow you to decorate the LINQ statement with your extension and get back the collection you desire. Either way you'll need to do some sort of conversion from the generic collection to your specialized collection -- either in the constructor or in the extension. Or you could do both...

public static class MyExtensions
{
     public static ProductCollection
                      ToProducts( this IEnumerable<Product> collection )
     {
          return new ProductCollection( collection );
     }
}


public class ProductCollection : BaseCollection<Product>
{
     ...

     public ProductCollection( IEnumerable<Product> collection )
              : base( collection )
     {
     }

     ...
 }


var products = (from p in HugeProductCollection
                where p.Vendor = currentVendor
                select p).ToProducts();
like image 69
tvanfosson Avatar answered Oct 14 '22 19:10

tvanfosson


I can suggest you a way in that you don't have to enumerate the collection 2 times:

abstract class BaseCollection<T> : List<T>
{
    public BaseCollection(IEnumerable<T> collection)
        : base(collection)
    {
    }
}

class PruductCollection : BaseCollection<Product>
{
    public PruductCollection(IEnumerable<Product> collection)
        : base(collection)
    {
    }
}

var products = from p in HugeProductCollection
               where p.Vendor = currentVendor
               select p;
PruductCollection objVendorProducts = new PruductCollection(products);
like image 31
bruno conde Avatar answered Oct 14 '22 20:10

bruno conde