在foreach循环中检查null

时间:2012-07-31 06:31:27

标签: c# loops foreach null

是否有更好的方法来执行以下操作:
在继续循环

之前,我需要在file.Headers上检查null
if (file.Headers != null)
{
  foreach (var h in file.Headers)
  {
   //set lots of properties & some other stuff
  }
}

简而言之,由于我的代码中出现了缩进级别,因此将foreach写入if中看起来有点难看。

是否会评估为

foreach(var h in (file.Headers != null))
{
  //do stuff
}

可能?

7 个答案:

答案 0 :(得分:97)

正如Rune建议的一个轻微的外观,你可以创建自己的扩展方法:

public static IEnumerable<T> OrEmptyIfNull<T>(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();
}

然后你可以写:

foreach (var header in file.Headers.OrEmptyIfNull())
{
}

根据品味更改名称:)

答案 1 :(得分:61)

假设file.Headers中的元素类型为T,则可以执行此操作

foreach(var header in file.Headers ?? Enumerable.Empty<T>()){
  //do stuff
}

如果file.Headers为null,这将创建一个空的可枚举T。但是,如果文件类型是您拥有的类型,我会考虑更改Headers的getter。 null是未知的值,所以如果可能,而不是使用null作为“我知道没有元素”当null实际(/原始)应解释为“我不知道是否有任何元素”使用一个空集,表示您知道集合中没有元素。这也是干的,因为你不必经常进行空检查。

编辑作为对Jons建议的跟进,您还可以创建一个将上述代码更改为

的扩展方法
foreach(var header in file.Headers.OrEmptyIfNull()){
  //do stuff
}

如果您无法更改getter,这将是我自己的首选,因为它通过赋予操作名称(OrEmptyIfNull)

更清楚地表达了意图

上面提到的扩展方法可能会使优化器无法进行某些优化检测。具体而言,可以消除与IList使用方法重载相关的那些

public static IList<T> OrEmptyIfNull<T>(this IList<T> source)
{
    return source ?? Array.Empty<T>();
}

答案 2 :(得分:13)

坦率地说,我建议:只需要进行null测试即可。 null测试只是一个brfalsebrfalse.s;其他一切都将涉及更多的工作(测试,分配,额外的方法调用,迭代器上不必要的GetEnumerator()MoveNext()Dispose()等。)

if测试简单,明显且高效。

答案 3 :(得分:11)

迭代之前的“if”很好,很少有“漂亮”的语义可以使你的代码不那么可读。

无论如何,如果缩进扰乱了你,你可以改变if来检查:

if(file.Headers == null)  
   return;

只有在headers属性中存在true值时才会进入foreach循环。

我能想到的另一个选择是在foreach循环中使用null-coalescing运算符,并完全避免空值检查。 样品:

List<int> collection = new List<int>();
collection = null;
foreach (var i in collection ?? Enumerable.Empty<int>())
{
    //your code here
}

(用真实对象/类型替换集合)

答案 4 :(得分:3)

我正在为这些场景使用一个很好的小扩展方法:

  public static class Extensions
  {
    public static IList<T> EnsureNotNull<T>(this IList<T> list)
    {
      return list ?? new List<T>();
    }
  }

鉴于Headers是类型列表,您可以执行以下操作:

foreach(var h in (file.Headers.EnsureNotNull()))
{
  //do stuff
}

答案 5 :(得分:2)

使用Null-conditional Operator和ForEach(),它比标准的foreach循环工作得更快 您必须将集合转换为List。

   listOfItems?.ForEach(item => // ... );

答案 6 :(得分:0)

对于某些情况,我更喜欢另一种通用变体,假设通常默认的集合构造函数返回空实例。

将此方法命名为NewIfDefault会更好。它不仅对集合有用,因此类型约束IEnumerable<T>可能是多余的。

public static TCollection EmptyIfDefault<TCollection, T>(this TCollection collection)
        where TCollection: class, IEnumerable<T>, new()
    {
        return collection ?? new TCollection();
    }