Это если(предметы!= null) лишний перед foreach (t пункт в пунктах)?


я часто сталкиваюсь примерно такой код:

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

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

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

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

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

12 62

12 ответов:

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

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

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

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

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

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

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

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

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

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

вы всегда можете проверить его с пустой список... но вот что я нашел на веб-сайте MSDN

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

если выражение имеет значение null, система.Создается исключение NullReferenceException.

вы можете поместить значение 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 => { 
  ...
});

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

items.ForEach(MethodThatTakesAnItem);

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

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

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

оператор foreach из C# язык (для каждого в Visual Basic) скрывает сложность перечислители. Таким образом, с помощью foreach есть рекомендуется вместо прямого манипулирование перечислителем.

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

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

второй бросит a NullReferenceException с

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

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

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

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