Apa gunanya .Any () dalam Daftar C # <>?

40

Saya telah mendiskusikan hal ini dengan kolega, dan kami tidak tahu apa gunanya .Anyuntuk setiap pemberian List<>, di C #.

Anda dapat memeriksa validitas elemen dalam array seperti pernyataan berikut:

if (MyList.Any()){ ...}  //Returns true or false

Yang persis sama dengan

if (MyList.Count() != 0) { ... }

dan jauh lebih umum, mudah dibaca dan jelas tentang maksud ifpernyataan itu.

Pada akhirnya, kami terjebak dengan pemikiran ini:

.Any() dapat digunakan, akan bekerja dengan baik, tetapi kurang jelas tentang maksud programmer, dan jika itu tidak boleh digunakan.

Tetapi kami merasa ini tidak mungkin benar; kita pasti kehilangan sesuatu.

Apakah kita?

Gil Sand
sumber
40
dengan cara apa kurang jelas tentang niat?
jk.
35
Saya menantang klaim Anda yang Any()kurang jelas: Any()tampak lebih jelas bagi saya, terutama dengan kondisi lambda. Menerjemahkan kode ke Bahasa Inggris di kepalaku, if(MyList.Count(o => o > 10) > 0)menjadi "Apakah jumlah item lebih besar dari 10 lebih dari 0?" sedangkan if(MyList.Any(o => o > 10))menjadi "Apakah ada item lebih besar dari 10?"
BlueRaja - Danny Pflughoeft 4-15
3
@SargeBorsch - hanya jika Anda lebih suka Heskel / penamaan fungsional, yang kebanyakan orang tidak.
Davor Ždralo
4
@ BlueRaja-DannyPflughoeft saya setuju. Saya pikir ada yang lebih jelas karena menghilangkan apa yang bisa dianggap sebagai angka ajaib.
Andy
2
@ SargeBorsch: SQL parallel to Anyis Exists. Nama Linq mungkin lebih terinspirasi oleh Haskell dan Python yang juga memiliki fungsi apa saja.
JacquesB

Jawaban:

95

Ingatlah bahwa Anyitu tidak beroperasi pada List; beroperasi pada IEnumerable, yang mewakili tipe konkret yang mungkin atau mungkin tidak memiliki Countproperti. Memang benar bahwa itu belum tentu yang terbaik untuk digunakan pada List, tapi itu pasti berguna di akhir permintaan LINQ. Dan yang lebih bermanfaat daripada versi standalone adalah override yang mengambil predikat seperti Where. Tidak ada yang dibangun di atas Listyang dekat nyaman atau ekspresif sebagai Anymetode perpanjangan predikat .

Selain itu, jika Anda menggunakan Count()(metode ekstensi LINQ untuk IEnumerable), daripada Count(properti aktif List), ia harus menghitung seluruh urutan jika tidak dapat mengoptimalkannya dengan mendeteksi bahwa tipe data mendasar Anda memiliki CountProperti . Jika Anda memiliki urutan panjang, ini bisa menjadi hit kinerja yang nyata ketika Anda tidak benar-benar peduli tentang apa yang menghitung adalah, dan hanya ingin tahu apakah ada setiap item dalam koleksi.

Mason Wheeler
sumber
19
Ini. Selain kinerja, Any()dengan predikat lebih ekspresif daripada membandingkan penimpaan Enumerable.Count()yang mengambil predikat dengan 0. :)
Dan J
1
Saya pikir ini menjelaskan dasar-dasarnya dengan sangat jelas yang menjelaskan jawaban terbaik.
Tarik
2
IMHO, Existssama nyaman dan ekspresifnya Any, dengan predikat. Menggunakan Count != 0properti pada a Listlebih normal daripada menggunakan Any(). Itu hanya preferensi pribadi. Saya juga telah melalui upaya mengubah _list_.Count()ke _list_.Countdalam kode grup saya. Itu membuat perbedaan nyata bagi saya.
Suncat2000
55

Ada perbedaan run time Count()bisa O (n) di mana Any()O (1)

Tanda
sumber
15
Count()juga tidak akan berhenti untuk iterator yang tak terbatas, sementara Any()akan, karena hanya perlu memanggil MoveNext()sekali.
Jon Purdy
3
Singkat dan akurat, tetapi ini lebih sebagai komentar daripada jawaban. Programer lebih suka jawaban yang menyelidiki mengapa dan memberikan sejumlah penjelasan. Pertimbangkan untuk mengedit jawaban Anda dan memperluas mengapa O (1) mungkin penting.
jawaban yang sangat bagus baru dipelajari saya harus menggunakan apa pun alih-alih menghitung == 0: d
MonsterMMORPG
4
Any(Func<T>)is O (n)
BlueRaja - Danny Pflughoeft
1
Dalam kasus spesifik List, kinerja adalah sama karena ekstensi menggunakan properti. Benar untuk semua koleksi yang mengimplementasikan ICollectionantarmuka.
Thorkil Holm-Jacobsen
9

Sebenarnya, perlu diingat bahwa ada properti List.Count , dan kemudian ada metode Enumerable.Count .

Dalam contoh Anda, Anda menggunakan Enumerable.Count()metode ini, yang harus mengulangi setiap item enumerasi untuk mengembalikan hasil. Itu jelas lebih lambat daripada menelepon Any()yang hanya perlu mengulang item pertama, jika ada.

EDIT:

Dalam komentar itu ditunjukkan, memang benar, bahwa Enumerable.Count()metode ekstensi tidak perlu mengulangi semua item jika mendeteksi bahwa enumerable juga merupakan ICollection<T>. Jadi dalam kasus a List<T>, menggunakan Countproperti atau metode sebenarnya tidak membuat perbedaan.

Sumber IEnumerable.Count :

public static int Count<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    ICollection<TSource> collectionoft = source as ICollection<TSource>;
    if (collectionoft != null) return collectionoft.Count;
    ICollection collection = source as ICollection;
    if (collection != null) return collection.Count;
    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator()) {
        checked {
            while (e.MoveNext()) count++;
        }
    }
    return count;
}
raja
sumber
Cukup adil. Lalu bagaimana dengan penggunaan properti .Count? bukankah itu membuat pembacaan secara signifikan lebih cepat, mungkin lebih cepat atau bahkan lebih cepat daripada memanggil .Any ()?
Gil Sand
4
Dengan List<T>perbedaan kinerja akan diabaikan. Jadi gunakan saja apa yang Anda inginkan. Tetapi untuk jenis IEnumerables lainnya, Anda hanya bisa memilih di antara Count()(metode), dan Any(), dan dalam hal itu, Any()akan selalu menjadi pemenang yang jelas untuk kasus penggunaan Anda dan harus lebih disukai. Untuk apa nilainya, saya pikir Any()cukup mudah dibaca dan jelas.
sstan
@ konstan ya kecuali jika ienumerable dapat dilemparkan ke collention maka itu dapat dioptimalkan dan itu tidak masalah.
Esben Skov Pedersen
2
Count()memiliki kompleksitas yang sama dengan Countuntuk ICollections, karena metode ekstensi kemudian menggunakan properti alih-alih iterasi.
Thorkil Holm-Jacobsen
Ekstensi Linq dioptimalkan untuk antarmuka yang dikenal - IList, ICollection. Diskusi kinerja di sini benar-benar berlebihan, bahkan jika itu adalah detail implementasi
Gusdor
6

Sebuah pertanyaan yang mengejutkan - saya menemukan niat list.Any()untuk menjadi lebih jelas daripada niat list.Count()!=0.

Maksud Maksud: Jika Anda membaca kode seseorang (dan Anda tidak menulisnya sendiri), apakah benar-benar jelas apa yang ingin dicapai oleh programmer dan mengapa itu ditulis tertulis seperti itu? Jika masalah umum diselesaikan dengan cara yang rumit dan tidak perlu, Anda segera menjadi curiga dan heran mengapa pengembang tidak menggunakan cara sederhana. Anda melihat-lihat kode dan mencoba melihat apakah Anda melewatkan sesuatu. Anda takut untuk mengubah kode karena Anda khawatir ada beberapa efek samping yang Anda lewatkan dan mengubahnya dapat menyebabkan masalah yang tidak terduga.

Maksud menggunakan Any()metode ini sepenuhnya jelas - Anda ingin tahu apakah ada elemen dalam daftar atau tidak.

Maksud dari ungkapan Count()!=0di sisi lain tidak jelas bagi pembaca. Tentu saja tidak sulit untuk melihat bahwa ekspresi memberitahu Anda apakah daftar itu kosong atau tidak. Pertanyaan muncul karena Anda menulisnya dengan cara tertentu daripada menggunakan metode standar. Mengapa Anda menggunakan Count()secara eksplisit? Jika Anda benar-benar hanya perlu tahu apakah ada setiap elemen dalam daftar, mengapa Anda ingin menghitung seluruh daftar pertama? Segera setelah Anda mencapai 1 Anda sudah memiliki jawaban. Jika sumbernya adalah iterator atas koleksi besar (mungkin tak terbatas) atau diterjemahkan ke sql, itu bisa membuat perbedaan besar dalam kinerja. Jadi mungkin penggunaan eksplisit Count () adalah untuk memaksa permintaan yang ditangguhkan untuk mengeksekusi atau melintasi iterator?

Tetapi sumbernya sebenarnya adalah di List<T>mana Count()O (1) dan tidak memiliki efek samping. Tetapi jika kode ini mengandalkan properti ini List<T>, maka mengapa tidak menggunakan Count-properti yang lebih jelas menunjukkan bahwa Anda mengharapkan operasi O (1) tanpa efek samping?

Seperti yang tertulis, list.Count()!=0melakukan persis sama dengan list.Any()kecuali itu tidak perlu lebih rumit dan maksudnya tidak jelas.

JacquesB
sumber
Saya membaca keduanya sebagai, "apakah daftar itu berisi barang?" Count()memiliki konversi tersirat yang saya akan hindari menggunakan, tetapi tidak jelas. Kompiler dapat mengoptimalkannya, yang hanya membuatnya menjadi pengkodean yang ceroboh.
Suncat2000
2

Mungkin itu hanya kata? Anyadalah kata sifat, tidak benar-benar mengatakan apa-apa. Berasal dari Jawa, saya akan menyebutnya isNonEmptyyang berisi kata kerja. Seorang pria SQL mungkin lebih suka EXISTS. Tapi mungkin Anypaling cocok di sistem C #.

Apa pun pilihan kata, begitu Anda terbiasa, itu harus menjadi lebih jelas. Apakah Anda akan bertanya "Apakah masih ada more than zerobotol bir". Apakah Anda berharap one or moreorang mulai menghitungnya sebelum mereka menjawab "Tidak, tidak ada any"?

maaartinus
sumber
1
Nama "any" masuk akal ketika Anda memikirkannya dalam istilah LINQ: Any()benar-benar merupakan jalan pintas untukAny(o => true)
BlueRaja - Danny Pflughoeft
Saya biasanya tidak menggunakan kosong untuk menggambarkan jika seorang enumerable punya anytjing untuk disebutkan. Tetapi "apakah ada setiap hal untuk menghitung" tampaknya alami bagi saya, dan Setiap karya terhadap pencacahan apapun.
Andy