2008-12-16 25 views
7

Sık sık özel koleksiyon nesnesiyle çalışırken linq'un sorunlu olduğunu görüyorum. GenellikleÖzel taban koleksiyonuna sahip Linq

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

koleksiyonları

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

olarak tanımlanır taban toplama AddRange daha bu koleksiyona bir linq anlatı sonuçlarını eklemek için daha iyi bir yolu var mı olarak defened edilir veya concat?

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

Nesne döndürdüğü nesne özel koleksiyonumun tipini oluşturduysa, bu hoş olurdu. Bunu yapmak için koleksiyonu iki kez numaralandırmanız gerektiği gibi.

EDIT: Yanıtları okuduktan sonra en iyi çözümün bir ToProduct() uzantısının uygulanması olduğunu düşünüyorum. C# 4.0'daki kovaryans/kontravaryans, bu tür problemleri çözmede yardımcı olur.

+1

- Çoğu linq sorguları tembel olarak değerlendirildiğinden, koleksiyon sadece AddRange çağrısı sırasında bir kez numaralandırılacaktır. –

+0

Bu, sorunumu çözdü ancak ne eksik olduğumu bilmiyorum çünkü bu geçici "BaseCollection " için bir gereksinim görmüyorum. Amacı nedir? – rtpHarry

cevap

7

Sorun şu ki, LINQ, IEnumerable<T> uzantı yöntemleri aracılığıyla Diziler, Listeler ve Sözlüklerin nasıl oluşturulacağını bilir, özel koleksiyonunuzu nasıl oluşturacağınızı bilmez. Özel koleksiyonunuzda IEnumerable<T> alan bir kurucu olabilir ya da yazabilirsiniz. Birincisi, LINQ sonucunu kurucunuzda doğrudan kullanmanıza izin verir, ikincisi LINQ deyimini uzantınızla birlikte süslemenize ve istediğiniz koleksiyonu geri almanıza izin verir. Her iki şekilde de jenerik koleksiyondan uzman koleksiyonunuza ya da kurucu ya da uzantıdan bir tür dönüşüm yapmanız gerekir. Yoksa

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

sana koleksiyon 2 kez numaralandırmak olmadığını bir yol önerebilir ... hem yapabilirdi:

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

Olabilir bir BindingList ile bu iş? BindingList'in IEnumerable alan bir kurucusu yoktur, ancak bunu uygular.

BindingList: Koleksiyon, ıbindinglist'te, ılist, ıcollection, IEnumerable ICancelAddNew, IRaiseItemChangedEvents "Koleksiyona Bunu yapmak için iki kere saymak gerekir gibi görünüyor gibi"

+0

BindingList gerçekten uygun değildir. OP, özel koleksiyonunu zaten doldurabiliyor, bu yüzden ek bir ara adım olarak bir BindingList eklemek yardımcı olmaz. – RogerN