web-dev-qa-db-ja.com

foreach(T item in items)の前にif(items!= null)は不要ですか?

私はしばしば次のようなコードに出くわします:

if ( items != null)
{
   foreach(T item in items)
   {
        //...
   }
}

基本的に、if条件は、foreachがnullでない場合にのみitemsブロックが実行されるようにします。 if条件が本当に必要なのか、foreachitems == null

つまり、単純に書くことができます

foreach(T item in items)
{
    //...
}

itemsがnullかどうかを心配せずに? if条件は不要ですか?または、これはitemstypeに依存しますか、またはTにも依存しますか?

79
Nawaz

(items!= null)かどうかを確認する必要があります。そうでない場合は、NullReferenceExceptionが発生します。ただし、次のようなことができます。

List<string> items = null;  
foreach (var item in items ?? new List<string>())
{
    item.Dump();
}

しかし、あなたはそれのパフォーマンスをチェックするかもしれません。だから、私はまだif(items!= null)を最初に持つことを好みます。

EricのLippertの提案に基づいて、コードを次のように変更しました。

List<string> items = null;  
foreach (var item in items ?? Enumerable.Empty<string>())
{
    item.Dump();
}
88
Vlad Bezden

C#6を使用すると、新しいnull条件演算子を List<T>.ForEach(Action<T>) (または独自の IEnumerable<T>.ForEach 拡張メソッド)。

List<string> items = null;
items?.ForEach(item =>
{
    // ...
});
51
kjbartel

ここでの実際の要点は、シーケンスが最初にヌルになることはほとんどないはずですです。すべてのプログラムで不変式にするだけで、シーケンスがある場合は決してヌルになりません。常に空のシーケンスまたは他の真正なシーケンスに初期化されます。

シーケンスがnullにならない場合、明らかにそれをチェックする必要はありません。

33
Eric Lippert

実際、その@Connectには機能のリクエストがあります: http://connect.Microsoft.com/VisualStudio/feedback/details/93497/foreach-should-check-for-null

そして、応答は非常に論理的です:

ほとんどのforeachループは、null以外のコレクションを反復する目的で作成されていると思います。 nullを反復処理しようとすると、コードを修正できるように例外が発生します。

10
Teoman Soygul

あなたは常にヌルリストでそれをテストすることができます...しかし、これは私がmsdnウェブサイトで見つけたものです

foreach-statement:
    foreach   (   type   identifier   in   expression   )   embedded-statement 

式の値がnullの場合、System.NullReferenceExceptionがスローされます。

5
nbz

それはスーパーフロースではありません。実行時に、アイテムはIEnumerableにキャストされ、そのGetEnumeratorメソッドが呼び出されます。それは失敗するアイテムの逆参照を引き起こします

2
boca

拡張メソッドでnullチェックをカプセル化し、ラムダを使用できます。

public static class EnumerableExtensions {
  public static void ForEach<T>(this IEnumerable<T> self, Action<T> action) {
    if (self != null) {
      foreach (var element in self) {
        action(element);
      }
    }
  }
}

コードは次のようになります。

items.ForEach(item => { 
  ...
});

Ifは、アイテムを受け取ってvoidを返すメソッドを呼び出すだけの場合、さらに簡潔になります。

items.ForEach(MethodThatTakesAnItem);
2
Jordão

これが必要です。それ以外の場合、foreachがコンテナにアクセスして反復を設定すると、例外が発生します。

内部では、foreachコレクションクラスに実装されたインターフェイス を使用して反復を実行します。一般的な同等のインターフェイスは here です。

C#言語のforeachステートメント(Visual Basicの場合)は、列挙子の複雑さを隠します。したがって、列挙子を直接操作する代わりにforeachを使用することをお勧めします。

1
Steve Townsend

C#6では、次のようにsthを書くことができます。

// some string from file or UI, i.e.:
// a) string s = "Hello, World!";
// b) string s = "";
// ...
var items = s?.Split(new char[] { ',', '!', ' ' }) ?? Enumerable.Empty<string>();  
foreach (var item in items)
{
    //..
}

基本的にはVlad Bezdenのソリューションですが、??常にnullではないため、foreachブラケット内でこのチェックを行うのではなく、foreachで生き残る配列を生成する式。

0
dr. rAI

コレクションがnullの場合、foreachはNullReferenceExceptionをスローするため、テストが必要です。実際に試してみるのは非常に簡単です。

List<string> items = null;
foreach(var item in items)
{
   Console.WriteLine(item);
}
0
Marius Bancila

2番目はメッセージObject reference not set to an instance of an object.NullReferenceExceptionをスローします

0
harryovers

前述のとおり、 here nullでないことを確認する必要があります。

Nullと評価される式は使用しないでください。

0
Reniuz