空传播运算符和 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 传播运算符是否有帮助?

空传播运算符和 foreach

我找到了另一种工作方式:

当使用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 => ...);