使用 C#7 的 foreach 声明中的空合并运算符
Null-coalescing operator in a foreach declaration using C#7
我正在查看 C# 7.0
中的 this code 示例,但我不确定幕后发生的事情以及此循环的性能。
foreach (var c in text ?? throw new ArgumentNullException(nameof(text)))
{
...
}
我的问题:
- 条件语句被命中一次还是多次(on
每次迭代)?
- 新语法看起来不一样,这样做有什么好处?
对于"how foreach works"来说,条件语句只会计算一次。
您可能想阅读有关 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/
我认为 "what are benefits" 是一种 opinion-based 问题。
在我看来,它没有带来任何好处,只是在术语或代码可读性方面很丑陋。
我建议使用 widely-used 常见的良好做法:
if (text == null) // or string.IsNullOrEmpty for strings
throw new ArgumentNullException(nameof(text));
foreach (var c in text)
{
// ...
}
可能,我们会在几年内看到 null-coalescing + throw exception 的用法,它将成为一个新的标准:)
您应该了解 foreach
内部代码以了解此 C#
功能。 foreach
语句中表达式的右边部分必须实现 IEnumerable(<T>)
接口,整个循环在内部是一个简单的 while
,像这样:
// here can be NullReferenceException
var en = text.GetEnumerator();
while(en.MoveNext())
{
var c = en.Current;
{
...
}
}
如您所见,此代码中有一个点可能会出现 NRE
,因此您需要检查可枚举的 before 整个循环或 Enumerable
extensions class,像这样:
if (text.IsNullOrWhitespace())
{
throw new ArgumentNullException(nameof(text));
}
// while loop here or text.SomeLinqCodeHere()
这里有些代码行并不是真正不必要的,它们添加了一些没有实际价值的熵。在简单 foreach
的情况下,它确实基于意见决定代码标准,但此功能的真正目的是将其与 C#7
中的其他新事物链接起来,例如 ?.
operator,如下所示:
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
但它为您的代码添加了一些类似合同的严格规则。
至于使用这种表达式的 foreach
循环的性能,如前所述,它不会受到影响,因为获取枚举器只发生一次,而 before真正的循环。
我正在查看 C# 7.0
中的 this code 示例,但我不确定幕后发生的事情以及此循环的性能。
foreach (var c in text ?? throw new ArgumentNullException(nameof(text)))
{
...
}
我的问题:
- 条件语句被命中一次还是多次(on 每次迭代)?
- 新语法看起来不一样,这样做有什么好处?
对于"how foreach works"来说,条件语句只会计算一次。
您可能想阅读有关 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/
我认为 "what are benefits" 是一种 opinion-based 问题。
在我看来,它没有带来任何好处,只是在术语或代码可读性方面很丑陋。
我建议使用 widely-used 常见的良好做法:
if (text == null) // or string.IsNullOrEmpty for strings
throw new ArgumentNullException(nameof(text));
foreach (var c in text)
{
// ...
}
可能,我们会在几年内看到 null-coalescing + throw exception 的用法,它将成为一个新的标准:)
您应该了解 foreach
内部代码以了解此 C#
功能。 foreach
语句中表达式的右边部分必须实现 IEnumerable(<T>)
接口,整个循环在内部是一个简单的 while
,像这样:
// here can be NullReferenceException
var en = text.GetEnumerator();
while(en.MoveNext())
{
var c = en.Current;
{
...
}
}
如您所见,此代码中有一个点可能会出现 NRE
,因此您需要检查可枚举的 before 整个循环或 Enumerable
extensions class,像这样:
if (text.IsNullOrWhitespace())
{
throw new ArgumentNullException(nameof(text));
}
// while loop here or text.SomeLinqCodeHere()
这里有些代码行并不是真正不必要的,它们添加了一些没有实际价值的熵。在简单 foreach
的情况下,它确实基于意见决定代码标准,但此功能的真正目的是将其与 C#7
中的其他新事物链接起来,例如 ?.
operator,如下所示:
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
但它为您的代码添加了一些类似合同的严格规则。
至于使用这种表达式的 foreach
循环的性能,如前所述,它不会受到影响,因为获取枚举器只发生一次,而 before真正的循环。