Frage In der foreach-Schleife auf Null prüfen


Gibt es eine schönere Art, folgendes zu tun:
Ich brauche eine Überprüfung auf null in der Datei.Headers passieren, bevor Sie mit der Schleife fortfahren

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

Kurz gesagt, es sieht ein wenig hässlich aus, die Foreach innerhalb des If zu schreiben, aufgrund des Ausmaßes der Einrückung, die in meinem Code passiert.

Ist etwas, was zu bewerten wäre

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

möglich?


58
2017-07-31 06:31


Ursprung


Antworten:


Genau wie eine kleine kosmetische Ergänzung zu Rune's Vorschlag, könntest du deine eigene Erweiterungsmethode erstellen:

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

Dann kannst du schreiben:

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

Ändern Sie den Namen nach Geschmack :)


84
2017-07-31 06:40



Angenommen, der Typ der Elemente in file.Headers ist T, können Sie dies tun

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

Dadurch wird ein leerer Enumerable von T if file.Headers ist null. Wenn der Typ der Datei ein Typ ist, den Sie besitzen, würde ich jedoch erwägen, den Getter von zu ändern Headers stattdessen. null ist der Wert von unbekannt, also wenn möglich, anstatt null als "Ich weiß, es gibt keine Elemente" zu verwenden, wenn null eigentlich (/ ursprünglich) als "Ich weiß nicht, ob es irgendwelche Elemente gibt" interpretiert wird, benutze einen leeren Satz, um das zu zeigen Ich weiß, dass es im Set keine Elemente gibt. Das wäre auch DRY'er, da Sie den Null-Check nicht so oft machen müssen.

BEARBEITEN Als Folge des Jons-Vorschlags könnten Sie auch eine Erweiterungsmethode erstellen, die den obigen Code ändert

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

In dem Fall, in dem Sie den Getter nicht ändern können, wäre dies mein eigener bevorzugt, da es die Absicht deutlicher ausdrückt, indem Sie der Operation einen Namen geben (OrEmptyIfNull)


53
2017-07-31 06:37



Ehrlich gesagt, rate ich: einfach die Saugen null Prüfung. EIN null Test ist gerade ein brfalse oder brfalse.s; alles andere wird viel mehr Arbeit erfordern (Tests, Zuweisungen, zusätzliche Methodenaufrufe, unnötig GetEnumerator(), MoveNext(), Dispose() auf dem Iterator usw.).

Ein if Test ist einfach, offensichtlich und effizient.


11
2017-07-31 06:46



Das "if" vor der Iteration ist in Ordnung. Wenige dieser "hübschen" Semantiken können Ihren Code weniger lesbar machen.

Wie auch immer, wenn der Einzug Sie stört, können Sie das if ändern:

if(file.Headers == null)  
   return;

Sie gelangen nur dann zur foreach-Schleife, wenn die Eigenschaft headers einen wahren Wert hat.

Eine weitere Option, über die ich nachdenken kann, ist die Verwendung des Null-Koaleszenz-Operators innerhalb Ihrer foreach-Schleife und die vollständige Vermeidung von Null-Überprüfungen. Probe:

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

(Ersetze die Sammlung mit deinem wahren Objekt / Typ)


9
2017-07-31 06:39



Ich verwende eine nette kleine Erweiterungsmethode für diese Szenarien:

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

Wenn Kopfzeilen eine Typenliste haben, können Sie Folgendes tun:

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

3
2017-07-31 06:40



Verwenden Null bedingter Operator und ForEach (), die schneller als Standard-foreach-Schleife arbeitet.
Sie müssen die Sammlung jedoch in "Liste" umwandeln.

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

1
2018-02-27 11:03



In einigen Fällen würde ich eine etwas andere, generische Variante bevorzugen, vorausgesetzt, dass Standard-Auflistungskonstruktoren in der Regel leere Instanzen zurückgeben.

Es wäre besser, diese Methode zu nennen NewIfDefault. Dies kann nicht nur für Sammlungen nützlich sein, sondern auch für Einschränkungen IEnumerable<T> ist vielleicht überflüssig.

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

0
2018-01-25 11:12