Является ли if (items!= Null) излишним перед foreach (элемент T в элементах)?

Я часто нахожу код вроде следующего:

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

В принципе, условие if гарантирует, что блок foreach будет выполняться, только если items не является нулевым. Мне интересно, действительно ли условие if, или foreach будет обрабатывать случай, если items == null.

Я имею в виду, могу ли я просто написать

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

не беспокоясь о том, является ли items нулевым или нет? Является ли условие if излишним? Или это зависит от типа items или, возможно, от T?

Ответ 1

Вам все равно нужно проверить, если (items!= null), иначе вы получите исключение NullReferenceException. Однако вы можете сделать что-то вроде этого:

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

но вы можете проверить его производительность. Поэтому я по-прежнему предпочитаю иметь, если сначала (items!= Null).

Основываясь на предложении Эрика Липперта, я изменил код на:

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

Ответ 2

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

Если последовательность никогда не равна нулю, то, очевидно, вам не нужно ее проверять.

Ответ 3

Используя С# 6, вы можете использовать новый оператор условных обозначений null вместе с List<T>.ForEach(Action<T>) (или ваш собственный IEnumerable<T>.ForEach).

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

Ответ 4

На самом деле на этом @Connect есть запрос функции: http://connect.microsoft.com/VisualStudio/feedback/details/93497/foreach-should-check-for-null

И ответ вполне логичен:

Я думаю, что большинство циклов foreach написано с целью итерации не нуль коллекция. Если вы пытаетесь итерации через нуль, вы должны получить ваше исключение, чтобы вы могли исправить ваш код.

Ответ 5

Вы всегда можете проверить его с помощью нулевого списка... но это то, что я нашел на веб-сайте msdn.

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

Если выражение имеет значение null, генерируется исключение System.NullReferenceException.

Ответ 6

Вы можете инкапсулировать нулевую проверку в методе расширения и использовать lambda:

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 => { 
  ...
});

Если может быть еще более кратким, если вы хотите просто вызвать метод, который принимает элемент, и возвращает void:

items.ForEach(MethodThatTakesAnItem);

Ответ 7

Это не суперплодно. Во время выполнения элементы будут отправлены в IEnumerable и будет вызван его метод GetEnumerator. Это приведет к разыменованию элементов, которые будут терпеть неудачу.

Ответ 8

Вам это нужно. Вы получите исключение, если foreach обратится к контейнеру, чтобы настроить итерацию в противном случае.

Под обложками foreach использует интерфейс, реализованный в классе коллекции для выполнения итерации. Общий эквивалентный интерфейс здесь.

Оператор foreach для С# язык (для каждого в Visual Basic) скрывает сложность счетчики. Поэтому, используя foreach рекомендуется вместо прямого манипулируя перечислителем.

Ответ 9

Тест необходим, потому что если коллекция имеет значение null, foreach будет вызывать исключение NullReferenceException. На самом деле это довольно просто попробовать.

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

Ответ 10

второй будет вызывать NullReferenceException с сообщением Object reference not set to an instance of an object.

Ответ 11

Как упоминалось здесь, вам нужно проверить, не является ли оно нулевым.

Не используйте выражение, которое оценивается как null.

Ответ 12

В С# 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)
{
    //..
}

В основном это решение Влада Бездена, но используя выражение всегда генерирует массив, который не является нулевым, и поэтому выживает foreach, а не имеет эту проверку внутри скобки foreach.