私はしばしば次のようなコードに出くわします:
if ( items != null)
{
foreach(T item in items)
{
//...
}
}
基本的に、if
条件は、foreach
がnullでない場合にのみitems
ブロックが実行されるようにします。 if
条件が本当に必要なのか、foreach
がitems == null
。
つまり、単純に書くことができます
foreach(T item in items)
{
//...
}
items
がnullかどうかを心配せずに? if
条件は不要ですか?または、これはitems
のtypeに依存しますか、またはT
にも依存しますか?
(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();
}
C#6を使用すると、新しいnull条件演算子を List<T>.ForEach(Action<T>)
(または独自の IEnumerable<T>.ForEach
拡張メソッド)。
List<string> items = null;
items?.ForEach(item =>
{
// ...
});
ここでの実際の要点は、シーケンスが最初にヌルになることはほとんどないはずですです。すべてのプログラムで不変式にするだけで、シーケンスがある場合は決してヌルになりません。常に空のシーケンスまたは他の真正なシーケンスに初期化されます。
シーケンスがnullにならない場合、明らかにそれをチェックする必要はありません。
実際、その@Connectには機能のリクエストがあります: http://connect.Microsoft.com/VisualStudio/feedback/details/93497/foreach-should-check-for-null
そして、応答は非常に論理的です:
ほとんどのforeachループは、null以外のコレクションを反復する目的で作成されていると思います。 nullを反復処理しようとすると、コードを修正できるように例外が発生します。
あなたは常にヌルリストでそれをテストすることができます...しかし、これは私がmsdnウェブサイトで見つけたものです
foreach-statement:
foreach ( type identifier in expression ) embedded-statement
式の値がnullの場合、System.NullReferenceExceptionがスローされます。
それはスーパーフロースではありません。実行時に、アイテムはIEnumerableにキャストされ、そのGetEnumeratorメソッドが呼び出されます。それは失敗するアイテムの逆参照を引き起こします
拡張メソッドで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);
これが必要です。それ以外の場合、foreach
がコンテナにアクセスして反復を設定すると、例外が発生します。
内部では、foreach
は コレクションクラスに実装されたインターフェイス を使用して反復を実行します。一般的な同等のインターフェイスは here です。
C#言語のforeachステートメント(Visual Basicの場合)は、列挙子の複雑さを隠します。したがって、列挙子を直接操作する代わりにforeachを使用することをお勧めします。
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で生き残る配列を生成する式。
コレクションがnullの場合、foreachはNullReferenceExceptionをスローするため、テストが必要です。実際に試してみるのは非常に簡単です。
List<string> items = null;
foreach(var item in items)
{
Console.WriteLine(item);
}
2番目はメッセージObject reference not set to an instance of an object.
でNullReferenceException
をスローします
前述のとおり、 here nullでないことを確認する必要があります。
Nullと評価される式は使用しないでください。