C#如何遍历可空列表?

Pie*_*rre -3 c# nullable

我正在与一个公开以下功能的API接口:

IEnumerable<Color?> getColors(long Id);
Run Code Online (Sandbox Code Playgroud)

我调用该函数:

IEnumerable<System.Drawing.Color?> colList = getColors(1);
Run Code Online (Sandbox Code Playgroud)

函数返回时,列表不为null。但是,当我尝试遍历列表时:

foreach (System.Drawing.Color col in colList)
{...}
Run Code Online (Sandbox Code Playgroud)

我什么都没有。没有进入循环。

遍历列表的正确方法是什么?

编辑:我终于想出了如何用这个伏都教得到一个列表计数:

int colCount = colList.Count<System.Drawing.Color?>();
Run Code Online (Sandbox Code Playgroud)

正如建议的那样,该计数确实为零。我现在向API提供者询问为什么这样做?

感谢所有提供正面和建设性建议的人。

The*_*aot 5

迭代器为空。这就是为什么它不进入循环的原因。


但是,请注意,循环中没有空值类型:

IEnumerable<System.Drawing.Color?> colList = getColors(1);
// System.Drawing.Color is not nullable:
foreach (System.Drawing.Color col in colList)
{
    Console.WriteLine(col);
}
Run Code Online (Sandbox Code Playgroud)

这将导致InvalidOperationException出现null时(因为它不能转换nullSystem.Drawing.Color)。使用System.Drawing.Color?(或使用var)代替。

例:

static void Main()
{
    foreach (var col in getColors(1))
    {
        Console.WriteLine(col == null);
    }

    Console.ReadLine();
}


static IEnumerable<System.Drawing.Color?> getColors(long Id)
{
    yield return null;
}
Run Code Online (Sandbox Code Playgroud)

输出真


关于使用扩展方法Count,请注意它可能在IEnumerable<Color?>?上进行迭代。在这种情况下,我建议使用ToArray并检查数组的大小。如此说来,知道a IEnumerable<Color?>也可以是无限的。

?:根据参考源Count可能正在投射ICollection<TSource>或从那里ICollection获取Count属性。否则它将迭代。

无限的简单例子IEnumerable<Color?>

static IEnumerable<System.Drawing.Color?> getColors(long Id)
{
    while (true)
    {
        yield return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果需要处理空情况,另一个选择是在循环内设置一个变量。如果设置了变量,则说明它不为空。

例:

bool isEmpty = true;
foreach (var col in getColors(1))
{
    isEmpty = false;
    // ...
}

if (isEmpty)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

正如德米特里•拜琴科(Dmitry Bychenko)指出的,您可能对OfType


附录

IEnumerable<T>接口只有一个GetEnumerator方法。然而,C#支持扩展方法,你会发现大量的推广方法IEnumerable<T>System.Linq.Enumerable,包括CountToArrayOfType

要使用这些扩展方法,请添加using System.Linq;到您的代码文件中。例:

using System.Linq;

// ...

static void Main()
{
    var colors = getColors(1).ToArray();
    // ...
}
Run Code Online (Sandbox Code Playgroud)

或将它们作为常规方法调用。例:

static void Main()
{
    var colors = System.Linq.Enumerable.ToArray(getColors(1));
    // ...
}
Run Code Online (Sandbox Code Playgroud)

最后两个代码示例是等效的。通常前者是首选。