关于c#:在foreach(项目中的T项)之前是否(items!= null)是多余的?

Is if(items != null) superfluous before foreach(T item in items)?

我经常遇到如下代码:

1
2
3
4
5
6
7
if ( items != null)
{
   foreach(T item in items)
   {
        //...
   }
}

基本上,if条件确保只有当items不为空时,foreach块才会执行。我想知道是否真的需要if条件,或者如果items == null条件,foreach是否会处理这个案件。

我是说,我能简单地写吗

1
2
3
4
foreach(T item in items)
{
    //...
}

不用担心EDOCX1[2]是否为空?if条件是否多余?或者这取决于items的类型,或者也可能取决于T的类型?


您仍然需要检查(项目!=null)否则将获得NullReferenceException。但是,您可以这样做:

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

但是你可以检查它的性能。所以我还是喜欢有if(物品!=空)首先。

根据埃里克的利珀特建议,我将代码改为:

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


使用c_6,您可以将新的空条件运算符与List.ForEach(Action)一起使用(或使用您自己的IEnumerable.ForEach扩展方法)。

1
2
3
4
5
List<string> items = null;
items?.ForEach(item =>
{
    // ...
});


这里真正的外卖应该是一个序列,一开始几乎不应该是空的。只需使它在所有程序中保持不变,即如果有序列,它就永远不会为空。它总是初始化为空序列或其他真正的序列。

如果序列从不为空,那么显然您不需要检查它。


实际上,@connect:http://connect.microsoft.com/VisualStudio/feedback/details/93497/foreach-should-check-for-null上有一个功能请求

答案很合理:

I think that most foreach loops are
written with the intent of iterating a
non-null collection. If you try
iterating through null you should get
your exception, so that you can fix
your code.


你可以用一个空列表来测试它…但这是我在msdn网站上找到的

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

If expression has the value null, a System.NullReferenceException is thrown.


可以在扩展方法中封装空签入并使用lambda:

1
2
3
4
5
6
7
8
9
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);
      }
    }
  }
}

代码变为:

1
2
3
items.ForEach(item => {
  ...
});

如果您只想调用一个接受项并返回void的方法,那么if可以更简洁:

1
items.ForEach(MethodThatTakesAnItem);


它不是多余的。在运行时,项将强制转换为IEnumerable,并调用其GetEnumerator方法。这将导致取消对将失败的项的引用


你确实需要这个。当foreach访问容器以设置迭代时,您将得到一个异常。

在封面下,foreach使用集合类上实现的接口来执行迭代。这里是通用等效接口。

The foreach statement of the C#
language (for each in Visual Basic)
hides the complexity of the
enumerators. Therefore, using foreach
is recommended instead of directly
manipulating the enumerator.


在C 6中,你可以这样写:

1
2
3
4
5
6
7
8
9
// 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)
{
    //..
}

这基本上是VladBezden的解决方案,但是使用??表达式始终生成一个不为空的数组,从而使foreach存活,而不是在foreach括号内进行此检查。


如前所述,您需要检查它是否不为空。

Do not use an expression that evaluates to null.


第二个将抛出一个带有消息Object reference not set to an instance of an object.NullReferenceException


测试是必需的,因为如果集合为空,foreach将引发NullReferenceException。实际上,尝试一下很简单。

1
2
3
4
5
List<string> items = null;
foreach(var item in items)
{
   Console.WriteLine(item);
}