コレクションのリクエストにアイテムが含まれない場合の予期される動作


13

次のものが与えられたとしましょう...

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

返すものが何もない場合、fubar.Things.All()が何を返すと期待しますか?

編集:意見をありがとう。少し待って、アップの多いエントリーを受け入れます。

私はこれまでの回答、特に空のコレクションを示唆するものに同意します。ベンダーは、上記の例に類似したいくつかの呼び出しでAPIを提供しました。昨年、APIを通じて460万ドルの収益を上げたベンダー、BTW。彼らは私が根本的に反対することをします-例外を投げます。


かなり堅実なコンセンサスのようです[ここ] [1]:空のコレクション。常に。[1]:stackoverflow.com/questions/1969993/...
ジェシーC.スライサー

データ型はThings何ですか?それが持っていることは理にかなっている場合Things、フィールドはnullを、それはあなたがあなたの呼び出しの前にnullをチェックしていなかったので、あなたが例外を受信するために理にかなっていますAll()。ただし、fubar.Thingsnullではなく空のコレクションを返す必要があると考える人々には同意します。
コリンD

私はあなたが何を得ているかわかります、コリン。この場合、モノが存在し、All()が静的であると想定できます。例外は、他の理由ではなく、空のコレクションに固有です。
-abscode

OMG彼らは例外をスローします...!o_O
スチュアートマークス

さて、より興味深い質問は、地球上の誰がそのような一般的なケースでスローする必要があるのか、またはスローイングを正当化するためにケースを特別にするものは何ですか?!
マーティンBa

回答:


29

2つの可能性(null空のコレクションを返す、または空のコレクションを返す)のうち、呼び出し元が戻り値のチェックをスキップできるため、空のコレクションを返すことを選択します。これを書く代わりに

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

彼らはこれを書くことができるでしょう:

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

この2番目のコードは、ネストレベルが1つ低いため、短くて読みやすくなっています。


2
「セットは空です」(アイテムなし)として概念的に理解するのも簡単だと思います。ヌルは「セットがありません」であり、まったく異なります。(これは、論理的に不可能なこともカバーする必要があります。奇数であり、偶数であるすべてのアイテムのセットは、nullではなく空である必要があります)。私は正直だではないことを確認するもの(論理的に)空集合を構成するであろう...(たとえあなたの島で裸にしている降圧、あなたの持ち物は空集合ではなく、ヌル一つです)
時計仕掛け-ミューズ

@ X-Zeroしかし、バックパックを背負っていない場合、バックパックを持っていないため、「バックパックの持ち物」はヌルセットを返す可能性があります。BackpackNotFoundExceptionである可能性がありますが、それ本当に予期しない場合のみです。たとえば、島のサバイバルゲームでは通常の状態である必要があります。
イズカタ

余分なヌルチェックは、夜寝るのに役立ちます。
ジョエルB

6

空のリストが必要です。theThingsまだオブジェクトですが、theThings.CountまたはtheThings.size()を返し0ます。


5

このような設計上の問題は、ヌルオブジェクトパターンによって対処されます

... null参照を使用してオブジェクト(たとえば、存在しない顧客)が存在しないことを伝える代わりに、期待されるインターフェイスを実装するが、メソッド本体が空のオブジェクトを使用します。動作するデフォルトの実装に対するこのアプローチの利点は、Nullオブジェクトが非常に予測可能であり、副作用がないことです。つまり、何もしません。

たとえば、関数はディレクトリ内のファイルのリストを取得し、それぞれに対して何らかのアクションを実行します。空のディレクトリの場合、1つの応答は、例外ではなく、リストではなくnull参照を返すことです。したがって、リストを期待するコードは、続行する前に実際にリストがあることを確認する必要があり、設計が複雑になる可能性があります...

あなたの場合に特に当てはまる提案(s Listがない場合に返すThing)は次のとおりです。

... 代わりにnullオブジェクト(つまり、空のリスト)を返すことにより、戻り値が実際にリストであることを確認する必要はありません。呼び出し側の関数は、通常どおりリストを単純に反復し、効果的には何もしません。ただし、戻り値がnullオブジェクト(空のリストなど)であるかどうかを確認し、必要に応じて異なる反応をさせることは可能です。


3

私見では、空の値を返す必要があります。私はC#については知りませんが、Javaではこれがあります:

  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#に相当するものはEnumerable.Empty<T>()、空を返しますIEnumerable<T>msdn.microsoft.com/en-us/library/bb341042.aspxを参照)
Avner Shahar-Kashtan

1
現在のドキュメントはこちら:docs.oracle.com/javase/7/docs/api/java/util/Collections.html-1.4.2のドキュメントは約10年前です。
スチュアートマーク

2

null値を返すよりも空のコレクションを返すのは、呼び出しコードでnull検証を記述することを回避できるためです。


2

彼らが意味する2つの解決策。

返されるものがゼロである場合、常に空のコレクションを返します!ディレクトリリストの場合を考えてみましょう。ディレクトリにファイルがない場合は、空のファイルのコレクションを返します。

一方、ディレクトリが存在しない場合、それは実際には適切ではありません。「何も返せない」とは、強制的に異なるものを意味します。その場合、状況に応じてnullを返すか、例外をスローする必要があります。何も問題がないように空のコレクションを返すだけではありません。


非常に合理的な説明。返される結果は無効な状態をカバーしてはなりません。これには例外があります。
イヴァイロスラヴォフ14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.