空传播算子和foreach

时间:2014-12-30 10:26:02

标签: c# null c#-6.0 null-propagation-operator

阅读了很多关于Null propagation operator ?.的内容,我没有回答是否在以下情况中有用。

抛出的代码:

int[] values = null;

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

为了实现这一点,我必须在访问null变量之前添加values检查。

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

我的问题:

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

4 个答案:

答案 0 :(得分:10)

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

当使用Jon Skeet(等人)精彩的MoreLinq扩展时,我可以在我的初始示例中使用ForEach extension method,如:

int[] values = null;

values?.ForEach(i=> /*...*/); // Does not throw, even values is null.

答案 1 :(得分:8)

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

答案 2 :(得分:4)

你会如何使用它?

您提供的代码:

int[] values = null;

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

enxpands into something:

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-coalescing operator (??)

int[] values = null;

foreach (var i in values ?? Enumerable.Empty<int>())
{
    // ...
}

答案 3 :(得分: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 => ...);