是否在foreach(item中的T item)之前是多余的(items!= null)?
我经常遇到如下代码:
if ( items != null) { foreach(T item in items) { //... } }
基本上, if
条件确保只有在items
不为null时才会执行foreach
块。 我想知道如果条件是真的需要,或者foreach
将处理的情况下,如果items == null
。
我的意思是,我可以简单写一下吗?
foreach(T item in items) { //... }
而不用担心items
是否为空? if
条件是多余的? 或者这取决于items
的types ,或者也可能在T
?
你仍然需要检查(items!= null)否则你将得到NullReferenceException。 不过你可以这样做:
List<string> items = null; foreach (var item in items ?? new List<string>()) { item.Dump(); }
但你可能会检查它的性能。 所以我还是喜欢if(items!= null)。
基于Eric的Lippertbuild议,我将代码更改为:
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上有一个function请求: http : //connect.microsoft.com/VisualStudio/feedback/details/93497/foreach-should-check-for-null
而且这个回应非常合乎逻辑:
我认为大多数foreach循环都是为了迭代非空集合而编写的。 如果你尝试迭代null,你应该得到你的exception,以便你可以修复你的代码。
你总是可以testing一个空列表…但这是我在msdn网站上find的
foreach-statement: foreach ( type identifier in expression ) embedded-statement
如果expression式的值为null,则引发System.NullReferenceException。
您可以在扩展方法中封装空检查并使用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);
这不是过分的。 在运行时,项目将被转换为IEnumerable,并且它的GetEnumerator方法将被调用。 这将导致失败的项目解引用
你确实需要这个。 当foreach
访问容器来设置迭代时,你会得到一个exception。
在下面, foreach
使用集合类上实现的接口来执行迭代。 通用的等价接口在这里 。
C#语言的foreach语句(对于Visual Basic中的每个语句)都隐藏了枚举器的复杂性。 因此,推荐使用foreach而不是直接操作枚举器。
testing是必要的,因为如果集合为null,foreach将抛出一个NullReferenceException。 这实际上很简单,尝试一下。
List<string> items = null; foreach(var item in items) { Console.WriteLine(item); }
第二个会抛出一个NullReferenceException
,消息Object reference not set to an instance of an object.
如上所述,您需要检查它是否为空。
不要使用计算结果为null的expression式。
在C#6中,你可以这样写:
// some string from file or UI, ie: // a) string s = "Hello, World!"; // b) string s = ""; // ... var items = s?.Split(new char[] { ',', '!', ' ' }) ?? Enumerable.Empty<string>(); foreach (var item in items) { //.. }
这基本上是弗拉德Bezden的解决scheme,但使用?? expression式总是生成一个不为null的数组,因此可以在foreach中生存,而不是在foreach括号中进行检查。