关于c#:在foreach循环中检查null

Check for null in foreach loop

是否有更好的方法来执行以下操作:在继续循环之前,我需要检查file.headers上是否存在空值。

1
2
3
4
5
6
7
if (file.Headers != null)
{
  foreach (var h in file.Headers)
  {
   //set lots of properties & some other stuff
  }
}

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

是可以评估的东西

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

可能吗?


就像对rune的建议稍加修饰一样,您可以创建自己的扩展方法:

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

然后你可以写:

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

根据口味更改名称:)


假设file.headers中的元素类型不是,您可以这样做

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

如果file.headers为空,这将创建一个空的可枚举的t。但是,如果文件的类型是您拥有的类型,我会考虑改为更改EDOCX1的getter(0)。null是unknown的值,因此,如果可能的话,不使用空值作为"我知道没有元素",当空值(原本)应解释为"我不知道是否有元素"时,使用空的集合来表示您知道集合中没有元素。那也会是干的,因为你不必经常做空检查。

作为对jons建议的后续操作,您还可以创建一个扩展方法,将上述代码更改为

1
2
3
foreach(var header in file.Headers.OrEmptyIfNull()){
  //do stuff
}

在你不能改变吸气剂的情况下,这将是我自己的首选,因为它通过给操作命名来更清楚地表达意图(orEmptyifNull)

上述扩展方法可能会使优化程序无法检测到某些优化。具体来说,使用方法重载与IList相关的那些可以消除

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


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

if测试简单、明显、有效。


迭代之前的"if"很好,很少有"pretty"语义可以降低代码的可读性。

不管怎样,如果压痕干扰了您,您可以更改if以检查:

1
2
if(file.Headers == null)  
   return;

只有当headers属性中有一个真值时,才能访问foreach循环。

我可以考虑的另一个选项是在foreach循环中使用空合并运算符,并完全避免空检查。样品:

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

(将集合替换为真正的对象/类型)


对于这些场景,我使用了一个很好的小扩展方法:

1
2
3
4
5
6
7
  public static class Extensions
  {
    public static IList<T> EnsureNotNull<T>(this IList<T> list)
    {
      return list ?? new List<T>();
    }
  }

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

1
2
3
4
foreach(var h in (file.Headers.EnsureNotNull()))
{
  //do stuff
}


使用空条件运算符和foreach(),它的工作速度比标准foreach循环快。不过,您必须将集合强制转换为列表。

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


在某些情况下,我更倾向于使用另一个通用变量,假定默认集合构造函数通常返回空实例。

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

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