空传播运算符和 foreach
本文关键字:foreach 运算符 传播 | 更新日期: 2023-09-27 18:35:36
阅读了很多关于 Null 传播运算符?.
的信息,我没有找到在以下情况下是否有帮助的答案。
抛出以下内容的代码:
int[] values = null;
foreach ( var i in values ) // Throws since values is null.
{
// ...
}
为了使其正常工作,我必须在访问values
变量之前添加null
检查。
上述代码很可能超出了 Null 传播运算符的设计注意事项范围。不过,可以肯定的是,我不得不问。
我的问题:
尝试访问foreach
循环中的null
集合时,Null 传播运算符是否有帮助?
我找到了另一种工作方式:
当使用Jon Skeet(等人)出色的MoreLinq扩展时,我可以在初始示例中使用一种ForEach
扩展方法,例如:
int[] values = null;
values?.ForEach(i=> /*...*/); // Does not throw, even values is null.
不,不是。它旨在允许以安全的方式访问对象的成员。在这种情况下,您必须检查数组是否为空。
你会如何使用它?
您提供的代码:
int[] values = null;
foreach (var i in values)
{
// ...
}
enxpands变成一些东西:
int[] values = null;
var enumerator = values.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
var i = enumerator.Current;
// ...
}
}
finally
{
var disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
我想你可以写这样的东西:
int[] values = null;
foreach (var i in values?.)
{
// ...
}
编译器必须将其扩展为如下所示的内容:
int[] values = null;
var enumerator = values?.GetEnumerator();
try
{
while (enumerator?.MoveNext() ?? false)
{
var i = enumerator.Current;
// ...
}
}
finally
{
var disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
请记住:
a = b?.M();
扩展到:
a = b == null ? null : b.M();
如果你不想显式编写 if
语句,你总是可以依靠旧的 null 合并运算符 (??):
int[] values = null;
foreach (var i in values ?? Enumerable.Empty<int>())
{
// ...
}
对于List<T>
,您可以使用list?.ForEach(i => ...);
,对于其他枚举,您可以创建自己的 ForEach 扩展,如下所示:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
if (source == null) { return; }
foreach (T item in source) {
action(item);
}
}
你这样称呼它:myPossiblyNullEnumerable.ForEach(i => ...);
如果您希望 ForEach 扩展在调用空枚举时抛出,您可以保留空检查,并使用与列表版本相同的 elvis 语法调用它:myPossiblyNullEnumerable?.ForEach(i => ...);