C# 在 foreach 循环中检查 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11734380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 19:00:35  来源:igfitidea点击:

Check for null in foreach loop

c#loopsforeachnull

提问by Eminem

Is there a nicer way of doing the following:
I need a check for null to happen on file.Headers before proceeding with the loop

是否有更好的方法来执行以下操作:
在继续循环之前,我需要检查 file.Headers 上是否发生 null

if (file.Headers != null)
{
  foreach (var h in file.Headers)
  {
   //set lots of properties & some other stuff
  }
}

In short it looks a bit ugly to write the foreach inside the if due to the level of indentation happening in my code.

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

Is something that would evaluate to

是评估为

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

possible?

可能的?

采纳答案by Jon Skeet

Just as a slight cosmetic addition to Rune's suggestion, you could create your own extension method:

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

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

Then you can write:

然后你可以写:

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

Change the name according to taste :)

根据口味更改名称:)

回答by Rune FS

Assuming that the type of elements in file.Headers is T you could do this

假设 file.Headers 中的元素类型是 T 你可以这样做

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

this will create an empty enumerable of T if file.Headers is null. If the type of file is a type you own I would, however, consider changing the getter of Headersinstead. nullis the value of unknown so if possible instead of using null as "I know there are no elements" when null actually(/originally) should be interpreted as "I don't know if there are any elements" use an empty set to show that you know there are no elements in the set. That would also be DRY'er since you won't have to do the null check as often.

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

EDITas a follow up on Jons suggestion, you could also create an extension method changing the above code to

编辑作为 Jons 建议的后续行动,您还可以创建一个扩展方法,将上述代码更改为

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

In the case where you can't change the getter, this would be my own preferred since it expresses the intention more clearly by giving the operation a name (OrEmptyIfNull)

在您无法更改 getter 的情况下,这将是我自己的首选,因为它通过为操作指定名称 (OrEmptyIfNull) 来更清楚地表达意图

The extension method mentioned above might make certain optimizations impossible for the optimizer to detect. Specifically, those that are related to IList using method overloading this can be eliminated

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

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

回答by Tamir

the "if" before the iteration is fine, few of those "pretty" semantics can make your code less readable.

迭代之前的“if”很好,那些“漂亮”的语义很少会降低您的代码的可读性。

anyway, if the indentation disturbs your, you can change the if to check:

无论如何,如果缩进干扰了您,您可以更改 if 以检查:

if(file.Headers == null)  
   return;

and you'll get to the foreach loop only when there is a true value at the headers property.

并且只有在 headers 属性中存在真值时,您才会进入 foreach 循环。

another option I can think about is using the null-coalescing operator inside your foreach loop and to completely avoid null checking. sample:

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

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

(replace the collection with your true object/type)

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

回答by Wolfgang Ziegler

I am using a nice little extension method for these scenarios:

我在这些场景中使用了一个不错的小扩展方法:

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

Given that Headers is of type list, you can do following:

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

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

回答by Marc Gravell

Frankly, I advise: just suck up the nulltest. A nulltest is justa brfalseor brfalse.s; everything else is going to involve much more work (tests, assignments, extra method calls, unnecessary GetEnumerator(), MoveNext(), Dispose()on the iterator, etc).

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

An iftest is simple, obvious, and efficient.

一个if测试是简单的,明显的,高效的。

回答by N. Kudryavtsev

For some cases I'd prefer slightly another, generic variant, assuming that, as a rule, default collection constructors return empty instances.

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

It would be better to name this method NewIfDefault. It can be useful not only for collections, so type constraint IEnumerable<T>is maybe redundant.

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

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

回答by Andrei Karcheuski

Using Null-conditional Operatorand ForEach() which works faster than standard foreach loop.
You have to cast the collection to List though.

使用空条件运算符和 ForEach() 比标准 foreach 循环工作得更快。
不过,您必须将集合转换为 List。

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