2014-12-30 5 views
13

Читайте много о Null propagation operator ?., я не нашел ответа, полезно ли это в следующем сценарии.Оператор нулевого распространения и foreach

Код, который бросает:

int[] values = null; 

foreach (var i in values) // Throws since values is null. 
{ 
    // ... 
} 

Чтобы сделать эту работу, я должен добавить null проверки перед доступом к переменным values.

Скорее всего, вышеуказанный код выходит за рамки соображений проектирования для оператора Null. Тем не менее, я должен спросить.

Мой вопрос:

ли оператор распространения Null полезно при попытке получить доступ к null коллекции в foreach цикле?

+7

Не ответ, но вы можете написать ' foreach (var i в значениях? Enumerable.Empty ()) ', чтобы избежать вложенности. –

+0

Или используйте ArrayList или List вместо этого :) – boctulus

+3

@Boctulus Это ссылочные типы с нулевым значением, вы знаете?!? –

ответ

7

Нет, это не так. Он предназначен для обеспечения доступа к элементам объекта безопасным образом. В этом случае вам нужно проверить, является ли массив null.

4

Как вы собираетесь использовать его?

код вы предоставили:

int[] values = null; 

foreach (var i in values) 
{ 
    // ... 
} 

enxpands в чем-то:

int[] values = null; 

var enumerator = values.GetEnumerator(); 
try 
{ 
    while (enumerator.MoveNext()) 
    { 
     var i = enumerator.Current; 
     // ... 
    } 
} 
finally 
{ 
    var disposable = enumerator as IDisposable; 
    if (disposable != null) 
    { 
     disposable.Dispose(); 
    } 
} 

Я думаю, вы могли бы написать что-то вроде этого:

int[] values = null; 

foreach (var i in values?.) 
{ 
    // ... 
} 

компилятор имел бы расширить его что-то вроде этого:

int[] values = null; 

var enumerator = values?.GetEnumerator(); 
try 
{ 
    while (enumerator?.MoveNext() ?? false) 
    { 
     var i = enumerator.Current; 
     // ... 
    } 
} 
finally 
{ 
    var disposable = enumerator as IDisposable; 
    if (disposable != null) 
    { 
     disposable.Dispose(); 
    } 
} 

И иметь в виду, что:

a = b?.M(); 

расширяется в:

a = b == null ? null : b.M(); 

Если вы хотите явно не написать if заявление, вы всегда можете положиться на старый добрый null-coalescing operator (??):

int[] values = null; 

foreach (var i in values ?? Enumerable.Empty<int>()) 
{ 
    // ... 
} 
+0

Нравится так: http: // stackoverflow. ком/а/31907661/7724 – bzlm

9

Я нашел еще один способ работы:

При использовании (и других) фантастических MoreLinq расширений Джона Скита, есть ForEach extension method, которые я могу использовать в моем исходном примере, как:

int[] values = null; 

values?.ForEach(i=> /*...*/); // Does not throw, even values is null. 
1

Для List<T> вы можете использовать list?.ForEach(i => ...); и для других перечислимых вы можете сделать ваше собственное расширение ForEach, как это:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) { 

    if (source == null) { return; } 

    foreach (T item in source) { 
     action(item); 
    } 
} 

Вы называете это следующим образом: myPossiblyNullEnumerable.ForEach(i => ...);

Если вы хотите, чтобы ваше расширение ForEach выбрасывалось при вызове нулевых перечислений, вы можете просто оставить нулевую проверку и называть его с тем же синтаксисом elvis, что и версия List: myPossiblyNullEnumerable?.ForEach(i => ...);

Смежные вопросы