2008-12-16 121 views
7

我經常在使用自定義集合對象時發現linq存在問題。 他們往往defened爲Linq與自定義集合對象

基地集合

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

集合定義爲

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

是否有更好的方法來從一個LINQ expession添加結果到這個集合比 的AddRange或concat?

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

這將是很好,如果從linq查詢返回的對象是我的自定義集合類型。因爲你似乎需要枚舉集合兩次才能做到這一點。

編輯: 在閱讀答案後,我認爲最好的解決方案是實現一個ToProduct()擴展。 不知道c#4.0中的協變/協變會有助於解決這類問題。

+1

。 「你似乎需要枚舉集合兩次做到這一點」 - 由於大多數linq查詢都是懶洋洋地評估的,集合只會在AddRange調用期間枚舉一次。 – 2008-12-19 00:46:34

+0

這解決了我的問題,但我不知道我錯過了什麼,因爲我沒有看到需要這個臨時`BaseCollection `。它的目的是什麼? – rtpHarry 2011-05-07 21:04:11

回答

7

問題是LINQ通過IEnumerable<T>上的擴展方法知道如何構建數組,列表和字典,但它不知道如何構建自定義集合。你可以讓你的自定義集合有一個構造函數,它需要一個IEnumerable<T>或者你可以寫你。前者允許你直接在你的構造函數中使用LINQ結果,後者允許你用你的擴展裝飾LINQ語句並找回你想要的集合。無論哪種方式,你需要做一些從泛型集合到專門化集合的轉換 - 無論是在構造函數中還是在擴展中。或者你可以兩者都做...

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(); 
2

我可以建議你在某種程度上你不必列舉收集2次:

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); 
-1

可以用一個的BindingList這項工作?因爲BindingList沒有一個構造函數,它會採用IEnumerable但是實現它。

的BindingList:收集,IBindingList的,IList的,ICollection的,IEnumerable的,ICancelAddNew,IRaiseItemChangedEvents