Özellik ve Count () yöntemi sayılsın mı?


85

Bir koleksiyonla çalışırken, nesnelerin sayısını elde etmenin iki yolu var; Count(özellik) ve Count()(yöntem). Temel farklılıkların ne olduğunu bilen var mı?

Yanılıyor olabilirim, ancak Countözelliği her zaman koşullu ifadelerde kullanıyorum çünkü Count()yöntemin koleksiyona karşı bir tür sorgu gerçekleştirdiğini varsayıyorum , burada Count'alma'dan önce atanmış olması gerekir. Ama bu bir tahmin - yanılıyorsam performansın etkilenip etkilenmeyeceğini bilmiyorum.

DÜZENLEME: Meraktan Count()dolayı, koleksiyon boşsa bir istisna mı atacak? Çünkü Countözelliğin sadece 0 döndürdüğünden oldukça eminim .


7
Her ikisi de boş koleksiyonlar için bir istisna atar, çünkü her ikisi de .operatörü boş olan bir şeye uygulamaya çalışıyor .
AaronLS

Yanıtlar:


110

Count()Uzantı yöntemi için kaynağı yeniden derlemek, nesnenin bir ICollection(genel veya başka türlü) olup olmadığını test ettiğini ve öyleyse basitçe temel alınan Countözelliği döndürdüğünü ortaya çıkarır :

Dolayısıyla, kodunuz Countarama yerine Count()erişirse, tür kontrolünü atlayabilirsiniz - teorik bir performans avantajı, ancak bunun fark edilir bir şey olacağından şüpheliyim!

// System.Linq.Enumerable
public static int Count<TSource>(this IEnumerable<TSource> source)
{
    checked
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        ICollection<TSource> collection = source as ICollection<TSource>;
        if (collection != null)
        {
            return collection.Count;
        }
        ICollection collection2 = source as ICollection;
        if (collection2 != null)
        {
            return collection2.Count;
        }
        int num = 0;
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                num++;
            }
        }
        return num;
    }
}

10
Bunu tersine mühendislik girişiminde bulunmak için +1, çok faydalı.
Polinom

7
Bununla birlikte, 3.5'te Count()genel olmayan ICollectionarayüzü kontrol etmediğini unutmayın . Bu yalnızca .NET 4'te eklenmiştir. Hem 3.5 hem de 4 genel ICollection<T>arabirimi kontrol eder .
thecoop

2
Hiçbir öğe içermeyen bir sıradaki sayıyı çağırmak bir istisna oluşturacaktır. Ancak Count () iyi çalışacaktır.
amesh

33

Performans, birini veya diğerini seçmek için yalnızca bir nedendir. Seçmek .Count(), kodunuzun daha genel olacağı anlamına gelir. Artık bir koleksiyon üretmeyen, ancak bunun yerine IEnumerable gibi daha genel bir kodun yeniden düzenlendiği durumlar oldu, ancak sonuç olarak başka kodlar bozuldu çünkü ona bağlıydı .Countve onu olarak değiştirmek zorunda kaldım .Count(). Her .Count()yerde kullanmak için bir noktaya değindiysem, kod muhtemelen daha yeniden kullanılabilir ve bakımı yapılabilir hale gelirdi. Bundan kurtulabilirseniz, genellikle daha genel arayüzleri kullanmayı seçmek en iyi seçeneğinizdir. Daha genel derken, daha fazla tür tarafından uygulanan ve böylece kod arasında daha fazla uyumluluk sağlayan daha basit arabirimi kastediyorum.

Daha .Count()iyidir demiyorum , sadece yazdığınız kodun yeniden kullanılabilirliğiyle daha çok ilgilenen başka hususlar olduğunu söylüyorum.


2
+1 Tartışmaya değerli bir katkı. Korumakta olduğum bazı kodlar bozuldu çünkü .Count özelliği HtmlAgilityPack'in bir sürüm yükseltmesinden sağ çıkamadı.
Dan Solovay

1
Bu iki ucu keskin kılıç olabilir. Ya bir gün birisi IEnumerable'ı gerçek bir üretici olacak şekilde değiştirmeye çalışırsa? Kod tabanına baktığımda, .Count () 'nin numaralandırılabilirin birden çok kez yinelenebileceğini varsaydığı birçok yer görüyorum
bashrc

@bashrc Doğru. Geliştiricinin kod değişikliğine karşı çerçeve kodu değiştirmeyi düşünürsek, geliştirici kodunun değişmesi daha olasıdır. Çerçevede bu tür bir değişiklik yapılsaydı, birçok şeyi bozardı. Geleneksel olarak bu durumlarda yeni koleksiyonlar / arayüzler sunarlar, böylece geliştiricilerin istediği gibi geçiş yapabilmesi sağlanır.
AaronLS

20

.Count()Yöntem olabilir akıllı yeterli veya söz konusu türü hakkında biliyorum ve eğer öyleyse, o olabilir yatan kullanmak.Count özelliğini.

Sonra tekrar, olmayabilir.

Koleksiyonun .Countkendisi bir mülke sahipse , performans söz konusu olduğunda en iyi seçeneğinizin bu olacağını varsaymanın güvenli olduğunu söyleyebilirim .

Eğer .Count() yöntem toplama hakkında bilmez, bir O (n) işlemi olacak, aş numaralandırma.


3
Özelliği kullanmak Countdaha iyi olabilir, ancak Count()yöntem oluşturma ICollection<T>.Countburada bir nevi belgelenmiştir: msdn.microsoft.com/en-us/library/bb338038(v=vs.110).aspx
nawfal

Neredeyse her şeyi nasıl bildiğini bilmiyorum.
35'te snr

5

Count()yöntem, bir öğesinin her bir öğesini yineleyen IEnumerable<>ve kaç öğe olduğunu döndüren bir genişletme yöntemidir . Örneği IEnumerableaslında bir ise List<>, Counttüm öğeleri yinelemek yerine özelliği döndürmek için optimize edilmiştir .


List <> olsa bile, kodumu daha genel tutmak için Count () yöntemini kullanıyorum. Belirli bir koleksiyon uygulamasına gerek olmayan IEnumerable <> kullanmak için sınıflarımı yeniden düzenlediğimde iyi.
AntonioR

3

Count()LINQ'dan bir genişletme yöntemi var mı - s, gerçek .NET koleksiyon nesneleri Countüzerinde bir özelliktir List.

Bu nedenle, Count()koleksiyon / sorgulanabilir nesneyi numaralandıracağı için neredeyse her zaman daha yavaş olacaktır. Liste, sıra, yığın vb Count. Üzerinde . Veya bir dizi için - Length.


3

Kısa Versiyon: Bir Countmülk ve bir mülk arasında seçim yapma şansınız varsaCount() yöntem her zaman özelliği seçin.

Aradaki fark esas olarak operasyonun verimliliği ile ilgilidir. Bir Countmülkü ortaya çıkaran tüm BCL koleksiyonları bunu O (1) tarzında yapar. Count()Kutu da yöntem olup, ve genellikle olacaktır, maliyet O (N). Bazı uygulamalar için denemek ve O (1) 'e getirmek için bazı kontroller var, ancak hiçbir şekilde garanti edilmiyor.


Bu cevabın count özelliğini kullanmak için daha makul olduğunu düşünüyorum
AT

3

Bir Countveya Lengthözellik varsa Count(), bunu genellikle içindeki öğelerin sayısını saymak için tüm koleksiyonu yineleyen yönteme tercih etmelisiniz . Count()Yöntem, örneğin bir LINQ to SQL veya LINQ to Entities kaynağına karşı olduğunda istisnalar olabilir , bu durumda veri kaynağına karşı bir sayma sorgusu gerçekleştirir. O zaman bile, eğer bir Countmülk varsa, muhtemelen yapacak daha az işi olduğundan, onu tercih etmek istersiniz.


3

Count()Yöntemi herhangi çalışır LINQ yöntemidir IEnumerable<>. Count()Yöntemin, sayımı bulmak için tüm koleksiyon üzerinde yinelemesini beklersiniz , ancak LINQ kodunun, bir Count özelliğinin var olup olmadığını algılamak için bazı optimizasyonlara sahip olduğuna ve öyleyse bunu kullandığına inanıyorum.

Yani ikisi de neredeyse aynı şeyleri yapmalı. Count özelliği muhtemelen biraz daha iyidir çünkü orada bir tür kontrolüne ihtiyaç yoktur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.