Проверить на null в цикле foreach


есть ли более приятный способ сделать следующее:
Мне нужна проверка для null, чтобы произойти в файле.Заголовки перед продолжением цикла

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

короче говоря, это выглядит немного некрасиво, чтобы написать foreach внутри if из-за уровня отступа, происходящего в моем коде.

это то, что будет оцениваться

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

возможно?

7 59

7 ответов:

просто как небольшое косметическое дополнение к предложению руны, вы можете создать свой собственный метод расширения:

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

тогда вы можете написать:

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

изменить название по вкусу:)

предполагая, что тип элементов в файл.Заголовки-это T вы могли бы сделать это

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

это создаст пустой перечисляемый файл T if.Заголовки-это null. Если тип файла является типом, которым вы владеете, я бы, однако, рассмотрел возможность изменения геттера Headers вместо. null это значение неизвестно, поэтому, если возможно, вместо использования null как "я знаю, что нет элементов", когда null на самом деле (/первоначально) должен интерпретироваться как "я не знаю, есть ли какие-либо элементы", используйте пустой набор чтобы показать, что вы знаете, что в наборе нет элементов. Это также будет DRY'ER, так как вам не придется делать нулевую проверку так часто.

EDIT в качестве продолжения предложения Jons вы также можете создать метод расширения, изменив приведенный выше код на

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

в случае, когда вы не можете изменить геттер, это было бы моим собственным предпочтением, поскольку он выражает намерение более четко, давая операции имя (OrEmptyIfNull)

честно говоря, я советую: просто подлизать

"Если "перед итерацией в порядке, немногие из этих" красивых " семантики могут сделать ваш код менее читаемым.

в любом случае, если отступ беспокоит вас, вы можете изменить если проверить:

if(file.Headers == null)  
   return;

и вы попадете в цикл foreach только тогда, когда в свойстве headers есть истинное значение.

другой вариант, о котором я могу думать,-это использование оператора null-coalescing внутри вашего цикла foreach и полностью избежать null проверочный. пример:

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

(замените коллекцию на ваш истинный объект / тип)

Я использую хороший метод расширения для этих сценариев:

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

учитывая, что заголовки имеют тип list, вы можете сделать следующее:

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

С помощью оператор и ForEach () который работает быстрее, чем стандартный цикл foreach.
Вы должны бросить коллекцию в список, хотя.

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

в некоторых случаях я бы предпочел немного другой, общий вариант, предполагая, что, как правило, конструкторы коллекции по умолчанию возвращают пустые экземпляры.

было бы лучше назвать этот метод NewIfDefault. Это может быть полезно не только для коллекции, поэтому ограничения типа IEnumerable<T> это может быть излишним.

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