Bir koleksiyon isteği sıfır öğeye sahip olduğunda beklenen davranış


13

Diyelim ki size aşağıdakiler veriliyor ...

List<Thing> theThings = fubar.Things.All();

Döndürülecek bir şey olmasaydı, fubar.Things.All () öğesinin geri dönmesini beklersiniz?

Düzenleme: Görüşleriniz için teşekkürler. Biraz bekleyeceğim ve girişleri en fazla yukarı ile kabul edeceğim.

Şimdiye kadar, özellikle boş bir koleksiyon öneren cevaplara katılıyorum. Bir satıcı, yukarıdaki örneğe benzer birkaç çağrı içeren bir API sağladı. Geçen yıl API'ları aracılığıyla 4.6 milyon dolar gelir elde eden bir satıcı BTW. Temelde aynı fikirde olmadığım bir şey yapıyorlar - bir istisna atıyorlar.


Oldukça sağlam bir fikir birliği gibi görünüyor [burada] [1]: Boş koleksiyon. Her zaman. [1]: stackoverflow.com/questions/1969993/…
Jesse C. Slicer

Veri türü ne için Things? ThingsAlanın null değerini döndürmesi mantıklıysa, bir istisna almanız mantıklıdır, çünkü çağrınızdan önce null olup olmadığını kontrol etmediniz All(). Ancak fubar.Thingsnull yerine boş bir koleksiyon döndürmesi gerektiğini düşünen insanlara katılıyorum .
Colin D

Ne elde ettiğini görüyorum, Colin. Bu durumda, Things (Var) öğelerinin var olduğunu ve All () öğesinin statik olduğunu varsayabilirsiniz. İstisna, koleksiyonun boş olmasıyla ilgilidir, başka bir neden değildir.
abscode

OMG bir istisna atıyorlar ...! o_O
Stuart Marks

Şimdi, daha ilginç bir soru, dünyada böyle bir jenerik durumda herkesin atmak zorunda kalmasının sebebi ya da davanın Atma garantisini bu kadar özel kılan şey ne olurdu ?!
Martin Ba

Yanıtlar:


29

İki olasılıktan (yani bir geri dönen nullveya boş bir koleksiyon dönen) boş bir koleksiyon dönen seçer, çünkü arayanın döndürülen değerin kontrolünü atlamasını sağlar. Bunu yazmak yerine

List<Thing> theThings = fubar.Things.All();
if (theThings != null) {
    for (Thing t : theThings) {
        t.doSomething();
    }
}

bunu yazabileceklerdi:

List<Thing> theThings = fubar.Things.All();
for (Thing t : theThings) {
    t.doSomething();
}

Bu ikinci kod parçası daha kısadır ve okunması daha kolaydır, çünkü iç içe geçme seviyesi bir azalır.


2
Sanırım kavramsal olarak 'set boş' (öğe yok) olarak anlamayı daha kolay bulurdum. Null, 'set yok', ki bu oldukça farklı. (Bu aynı zamanda mantıksal imkansızlıklar olan şeyleri de kapsamalıdır - garip olan ve hatta boş olması gereken tüm öğeler kümesi boş olmalıdır). Dürüst olmak gerekirse (mantıksal olarak) null bir set oluşturacağından emin değilim ... (bir adada çıplak olsanız bile, eşyalarınız boş değil, boş bir settir)
Clockwork-Muse

@ X-Zero Ama çıplak kalıyorsanız, sırt çantanız bile olmadığından, "sırt çantasındaki eşyalar" null bir set döndürebilir. Bu olabilir bir BackpackNotFoundException olabilir ama gerçekten beklenmedik yalnızca. Bir ada hayatta kalma oyununda normal bir durum olmalı.
Izkata

Ekstra null kontrol geceleri uyku bana yardımcı olur.
Joel B

6

Boş bir liste beklerdim. theThingsHala bir nesne olurdu, ama theThings.Countya theThings.size()dönecekti 0.


5

Bunun gibi tasarım sorunları Boş Nesne kalıbıyla giderilir

... Bir nesnenin (örneğin, var olmayan bir müşteri) yokluğunu iletmek için null referans kullanmak yerine, beklenen arabirimi uygulayan, ancak yöntem gövdesi boş olan bir nesne kullanılır. Varsayılan bir uygulama üzerinde bu yaklaşımın avantajı, bir Boş Nesnenin çok öngörülebilir olması ve hiçbir yan etkisi olmamasıdır: hiçbir şey yapmaz.

Örneğin, bir işlev bir dizindeki dosyaların listesini alabilir ve her biri üzerinde bazı eylemler gerçekleştirebilir. Boş bir dizin olması durumunda, yanıtlardan biri liste yerine istisna atmak veya boş bir başvuru döndürmek olabilir. Bu nedenle, bir listeyi bekleyen kod, devam etmeden önce bir listeye sahip olduğunu doğrulamalıdır, bu da tasarımı karmaşıklaştırabilir ...

Özellikle davanızda geçerli olan öneri ( Listhiç olmadığında geri dönüş Thing):

... Bunun yerine null bir nesne (yani boş bir liste ) döndürerek , dönüş değerinin aslında bir liste olduğunu doğrulamaya gerek yoktur. Çağıran işlev, listeyi normal olarak yineleyerek etkin bir şekilde hiçbir şey yapmaz. Bununla birlikte, dönüş değerinin boş bir nesne (örneğin boş bir liste) olup olmadığını kontrol etmek ve istenirse farklı tepki vermek hala mümkündür.


3

IMHO, bir EMPTY değeri döndürmelisiniz. C # hakkında bilmiyorum, ama Java'da bu var:

  List list = Collections.EMPTY_LIST;
  Set set = Collections.EMPTY_SET;
  Map map = Collections.EMPTY_MAP;

  // For the type-safe 
  List<String> s = Collections.emptyList();
  Set<Long> l = Collections.emptySet();
  Map<Date> d = Collections.emptyMap();

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html


1
C # eşdeğeri, Enumerable.Empty<T>()boş bir değer döndürür IEnumerable<T>(bkz. Msdn.microsoft.com/en-us/library/bb341042.aspx )
Avner Shahar-Kashtan

1
Mevcut dokümanlar burada: docs.oracle.com/javase/7/docs/api/java/util/Collections.html - 1.4.2 dokümanlar şu an yaklaşık on yaşında.
Stuart Marks

2

Bu şekilde arama kodunda boş bir doğrulama yazmaktan kaçınabileceğiniz için boş bir değer döndürerek boş bir değer döndürürdüm.


2

İki çözüm farklı şeyler ifade ediyor.

Eğer iade ettiğiniz şeyin sadece sıfırı varsa, DAİMA boş bir koleksiyon iade edersiniz! Bir dizin listesinin durumunu ele alın. Dizinde dosya yoksa, boş bir dosya koleksiyonu döndürürsünüz.

Öte yandan, dizin yoksa, bu gerçekten uygun değildir. "Hiçbir şey geri dönemem" tamamen farklı bir şey demektir. Bu durumda, duruma bağlı olarak null döndürmeli veya istisna atamalısınız, hiçbir şey yanlış değil gibi boş bir koleksiyon döndürmeyin.


Çok makul bir açıklama. Geri gönderilen sonuç geçersiz durumu kapsamamalı, bunun için istisnalarımız var.
Ivaylo Slavov
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.