2012-02-14 17 views
21

Aşağıdaki kodla beklenmeyen bir sorunla karşılaştım.OrderBy ve Liste vs. IOrderedEnumerable

List<string> items = new List<string>(); 
items = items.OrderBy(item => item); 

Bu kod hatası oluşturur:

Cannot implicitly convert type 'System.Linq.IOrderedEnumerable' to 'System.Collections.Generic.List'. An explicit conversion exists (are you missing a cast?)

Ben tip IEnumerable<string> olması için items değiştirebilir görünür ve hata ortadan kalkar. Ancak, IEnumerable'un desteklemediği listeye öğe ekleyebilmem gerekiyor.

Birisi bu hatayı anlamama yardımcı olabilir ve en kolay düzeltme nedir? Sonucu almayı güvenli midir?

+0

İlk önce boş bir liste oluşturuyorsunuz ve sonra bu boş listeyi sıralamaya çalışıyorsunuz? – hvd

+26

@hvd: Tabii ki değil. Burada yaptığım şey, sorunu olabildiğince az kodla gösteren basit bir snippet oluşturmaya çalışıyor. –

+2

Ancak sorunu göstermiyor, çünkü o kadar çok sildiniz ki, sıralamanız gereken bir listeye sahip olup olmadığın ya da denemek istediğiniz sayısız değeriniz olup olmadığı net değil sıralamak ve bir listeye girmek. – hvd

cevap

36

Neden sadece listeyi Sort() örnek yöntemini kullanarak değil d; Daha sonra isterseniz öğelere ekleyebilirsiniz:

List<string> items = GetSomeItems(); 
items.Sort(); 

Veya ikili arama ağacı gibi düzenli bir koleksiyon kullanın. İhtiyaçlarınıza bağlı olarak SortedSet<T> faturaya uyabilir. başkaları tarafından önerilen

çözüm:

items = items.OrderBy(item => item).ToList(); 

... Yeni bir sırayla özgün öğelerle başka bir liste oluşturur. Bu, yalnızca orijinal siparişi başka bir amaç için saklamanız gerektiğinde kullanışlıdır; Listeyi sıralamaktan ziyade daha fazla hafıza kaybıdır. List<T>IOrderedEnumerable<T> bir alt tipi değildir, bu nedenle ikisi arasında örtülü hiçbir referans dönüşüm gerçekleşmesi:

Bildiğim kadarıyla hatayı anlayarak olarak, çok basit. Derleyicinin önerdiği açık döküm, derleyiciyi tatmin edecek, ancak OrderBy<T> tarafından döndürülen nesne List<T>'dan devralmadığı için çalışma zamanında başarısız olur. Eğer Linq gerekmez dizeleri listesini sıralama için

List<MyType> items = GetSomeItems(); 
items.Sort((a, b) => a.Key.CompareTo(b.Key)); 
+1

Teşekkürler, bu en eksiksiz cevap gibi görünüyor. Sort() 'i kullanma fikrini çok beğendim, ancak bu oldukça uygun değil çünkü gerçek verilerim bir sınıf ve daha karmaşık sıralama kuralları istiyorum. Ama sanırım her zaman özel bir karşılaştırma yapabilirim. –

+0

@JonathanWood sınıfının sipariş bağlamında bağımlı değilse, sınıfın üzerinde 'IComparable ' uygulayabilir ve bu '()' o uygulamayı kullanır List.Sort. – phoog

+1

Ayrıca 'Karşılaştırma ' veya lambda 'geçebilir (a, b) => bir ayırma işlevi (inline ya da bir yöntem adı geçirilerek) ve bazen daha uygundur, int' döndürür. Aynı zamanda bir 'Karşılaştırma ' temsilci götüren bir 'Sort' aşırı yük var .NET 4 – jessehouwing

14

IEnumerable ürününü List ürününe dönüştürmeniz gerekir. Bu deneyin:

items = items.OrderBy(item => item).ToList(); 
+0

Teşekkürler. ToList() 'in ne kadar verimli olduğunu bilen var mı? Örneğin, yeni bir koleksiyon tahsis etmesi ve daha sonra listedeki her öğeyi kopyalaması gerekir. –

+1

@JonathanWood Muhtemelen. Bulmak için Reflektör'ü kullanabilirsiniz. Orijinal listeyi korumanız gerekmiyorsa, bunun yerine 'Sort()' seçeneğine gideceğim. –

+4

@JonathanWood evet, yeni bir liste ayırır. – phoog

6

bu

items = items.OrderBy(item => item).ToList(); 
5

LINQ en ToList kullanmak gerekir deneyin() yöntemi

items = items.OrderBy(item => item).ToList(); 

Sen IEnumerable'dan < doğrudan döküm olamaz> Listeye <>

4

: tip MyType varsayarak

DÜZENLEME

List<T>.Sort(Comparison<T>) bir örneği, bazı tip tip T bir Key özelliğine T : IComparable<T> sahiptir ilk etapta - sadece Sort() kullanın:

List<string> items = new List<string>(); 
//add items here 
items.Sort(); 
1

OrderBy(), IEnumerable - ve Not Listesinin bir uzantısı yöntemidir.

Derleyici, OrderBy() uzantı yöntemiyle karşılaştığında, aralık değişkenini IComparer ve diğ. Kullanılarak CreateOrderedEnumerable yöntemiyle gereken sıralamayı gerçekleştirebileceği bir IOrderedEnumerable değerine çevirir. Sıralandığında, derleyici, genellikle IEnumerable olarak değişkeni tükürür.

Öneri: LinQ fıkrada 'öğeleri' yazmak için var anahtar sözcüğünü kullanın. Sıralama() ve çalışacaktır ToList() yöntemlerini kullanarak yukarıda sunulan

şüphesiz

seçenekler - bunları kullanarak ancak açgözlü operatörleri içerir ve Gecikmeli yüklemenin avantajı kaybederler.

Burada Sort() ve OrderBy() arasında çalışan iyi bir arıza: C# Sort and OrderBy comparison.