18

阅读了很多关于Null 传播运算符?.的内容,我发现它在以下场景中是否有帮助没有答案。

抛出的代码:

int[] values = null;

foreach ( var i in values ) // Throws since values is null.
{
    // ...
}

为了使它工作,我必须null在访问values变量之前添加一个检查。

上述代码很可能超出了 Null 传播运算符的设计考虑范围。不过,可以肯定的是,我不得不问。

我的问题:

尝试在循环中访问null集合时,Null 传播运算符是否有用?foreach

4

4 回答 4

12

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

当使用 Jon Skeet (et al) 出色的MoreLinq扩展时,有一种ForEach扩展方法可以在我的初始示例中使用,例如:

int[] values = null;

values?.ForEach(i=> /*...*/); // Does not throw, even values is null.
于 2015-08-09T18:46:30.830 回答
8

不它不是。它旨在允许以安全的方式访问对象的成员。在这种情况下,您必须检查数组是否为null

于 2014-12-30T10:27:15.207 回答
4

你打算如何使用它?

您提供的代码:

int[] values = null;

foreach (var i in values)
{
    // ...
}

扩展为:

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语句,则始终可以依赖旧的空合并运算符 (??)

int[] values = null;

foreach (var i in values ?? Enumerable.Empty<int>())
{
    // ...
}
于 2014-12-30T21:45:48.370 回答
1

对于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 扩展在调用 null 枚举时抛出,你可以离开 null 检查,并使用与 List 版本相同的 elvis 语法调用它:myPossiblyNullEnumerable?.ForEach(i => ...);

于 2017-11-16T13:34:46.047 回答