使用C#7的foreach声明中的空合并运算符

时间:2017-02-16 03:16:21

标签: c# null-coalescing-operator c#-7.0

我正在查看foreach (var c in text ?? throw new ArgumentNullException(nameof(text))) { ... } 中的SelectedItem示例,我不确定幕后发生了什么以及此循环的效果。

const MyRecord = Record({
  foo: 'null'
}, 'MyRecord') // <- Be sure to add a name field to your record 

我的问题:

  1. 条件语句是一次还是多次打击(打开 每次迭代)?
  2. 新语法看起来不同,这样做有什么好处?

2 个答案:

答案 0 :(得分:9)

就“foreach如何运作”而言,条件陈述只会计算一次。

您可能想要阅读有关foreach循环如何在这些问题中起作用的更多信息:
How do foreach loops work in C#?
Does foreach evaluate the array at every iteration?

感谢Svek解释这是一个新的C#7.0功能,它将在Visual Studio 2017 RC之后发布:
http://structuredsight.com/2016/09/01/c-7-additions-throw-expressions/

我认为“什么是好处”是一种基于意见的问题 在我看来,它没有带来什么好处,只是在术语或代码可读性上是丑陋的 我建议使用广泛使用的通用良好做法:

if (text == null) // or string.IsNullOrEmpty for strings
    throw new ArgumentNullException(nameof(text));

foreach (var c in text)
{
    // ...
}

可能我们会在几年内看到null-coalescing + throw异常使用,它将成为一个新标准:)

答案 1 :(得分:2)

您应该了解<?php $array = array(); $uniqueArray = array_unique($array); for ( $i = 0; $i < sizeof($uniqueArray); ++$i ) { if ( in_array($uniqueArray[$i], $array) ) { // Item has duplicates } else { // item is unique } } ?> 内部代码,以了解此foreach功能。 C#语句中表达式的右侧部分必须实现foreach接口,整个循环在内部是一个简单的IEnumerable(<T>),如下所示:

while

正如您所看到的,此代码中有一点// here can be NullReferenceException var en = text.GetEnumerator(); while(en.MoveNext()) { var c = en.Current; { ... } } 可能会发生,因此您需要检查可以在>整个循环之前的可识别Enumerable extensions class,如下所示:

NRE

这里有一些代码行并不是真的没必要,添加一些没有实际价值的熵。如果是简单的if (text.IsNullOrWhitespace()) { throw new ArgumentNullException(nameof(text)); } // while loop here or text.SomeLinqCodeHere() ,它确实是基于意见的关于代码标准的决定,但此功能的真正目的是将其与foreach中的其他新内容联系起来,如?. operator,如下所示:

C#7

在这种情况下,抛出异常类似于代码行末尾的注释:

int? length = customers?.Length ?? throw new ...;
Customer first = customers?[0] ?? throw new ...;  
int? count = customers?[0]?.Orders?.Count() ?? throw new ...;

但它为您的代码添加了一些严格的类似合同的规则。

对于具有这种表达式的int? length = customers?.Length; // should not be null Customer first = customers?[0]; // should not be null int? count = customers?[0]?.Orders?.Count(); // should not be null 循环的性能,正如已经说过的那样,它不会受到影响,因为枚举器只出现一次,出现真正循环。