web-dev-qa-db-ja.com

foreachループでnullをチェックします

以下を行うより良い方法があります:
file.Headersでnullをチェックしてからループに進む必要があります

if (file.Headers != null)
{
  foreach (var h in file.Headers)
  {
   //set lots of properties & some other stuff
  }
}

要するに、コード内で発生するインデントのレベルのために、if内にforeachを書くのは少しbitいように見えます。

評価されるものです

foreach(var h in (file.Headers != null))
{
  //do stuff
}

可能?

70
Eminem

ルーンの提案へのわずかな化粧品の追加と同様に、独自の拡張メソッドを作成できます。

public static IEnumerable<T> OrEmptyIfNull<T>(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();
}

その後、あなたは書くことができます:

foreach (var header in file.Headers.OrEmptyIfNull())
{
}

好みに応じて名前を変更してください:)

98
Jon Skeet

File.Headersの要素のタイプがTであると仮定すると、これを行うことができます

foreach(var header in file.Headers ?? Enumerable.Empty<T>()){
  //do stuff
}

これは、file.Headersがnullの場合、Tの空の列挙型を作成します。ただし、ファイルのタイプが自分が所有するタイプである場合は、代わりにHeadersのゲッターを変更することを検討してください。 nullはunknownの値なので、可能であれば、nullを実際に(/元々)nullを「要素が存在するかどうかわからない」と解釈する場合、nullを「要素がないことを知っている」として使用する代わりに空のセットを使用して、セットに要素がないことを示します。また、nullチェックを頻繁に行う必要がないので、これはより乾燥しています。

[〜#〜] edit [〜#〜] Jonsの提案のフォローアップとして、上記のコードを次のように変更する拡張メソッドを作成することもできます。

foreach(var header in file.Headers.OrEmptyIfNull()){
  //do stuff
}

ゲッターを変更できない場合は、操作に名前(OrEmptyIfNull)を付けることで意図をより明確に表現するため、これは自分の好みです。

上記の拡張方法では、オプティマイザーが特定の最適化を検出できない場合があります。具体的には、これをオーバーロードするメソッドを使用してIListに関連するものを削除できます

public static IList<T> OrEmptyIfNull<T>(this IList<T> source)
{
    return source ?? Array.Empty<T>();
}
64
Rune FS

率直に言って、私はアドバイスします:nullテストを吸うだけです。 nullテストはjust a brfalseまたは_brfalse.s_;です。それ以外のすべての作業には、より多くの作業が必要になります(テスト、割り当て、追加のメソッド呼び出し、イテレーターでの不要なGetEnumerator()MoveNext()Dispose()など)。

ifテストは単純で、明白で、効率的です。

15
Marc Gravell

反復の前の「if」は問題ありませんが、これらの「きれいな」セマンティクスのいくつかはコードを読みにくくします。

とにかく、インデントが邪魔な場合は、チェックするifを変更できます。

if(file.Headers == null)  
   return;

そして、headersプロパティにtrue値がある場合にのみforeachループに到達します。

私が考えることができるもう1つのオプションは、foreachループ内でnull結合演算子を使用し、nullチェックを完全に回避することです。サンプル:

List<int> collection = new List<int>();
collection = null;
foreach (var i in collection ?? Enumerable.Empty<int>())
{
    //your code here
}

(コレクションを実際のオブジェクト/タイプに置き換えます)

11
Tamir

Null-conditional Operator およびForEach()を使用すると、標準のforeachループよりも高速に動作します。
ただし、コレクションをリストにキャストする必要があります。

   listOfItems?.ForEach(item => // ... );
4

私はこれらのシナリオにニースの小さな拡張メソッドを使用しています:

  public static class Extensions
  {
    public static IList<T> EnsureNotNull<T>(this IList<T> list)
    {
      return list ?? new List<T>();
    }
  }

Headersがタイプリストである場合、以下を実行できます。

foreach(var h in (file.Headers.EnsureNotNull()))
{
  //do stuff
}
3

場合によっては、原則として、デフォルトのコレクションコンストラクターが空のインスタンスを返すと仮定して、少し別の汎用バリアントを好む場合があります。

このメソッドにNewIfDefaultという名前を付ける方が良いでしょう。コレクションだけでなく、型制約IEnumerable<T>は冗長かもしれません。

public static TCollection EmptyIfDefault<TCollection, T>(this TCollection collection)
        where TCollection: class, IEnumerable<T>, new()
    {
        return collection ?? new TCollection();
    }
0
N. Kudryavtsev