C#中是否有"空列表"单例?

72 c# ienumerable singleton empty-list

在C#中,我使用LINQ和IEnumerable一点点.一切都很好(或至少大部分都是如此).

但是,在很多情况下,我发现自己需要一个空IEnumerable<X>的默认值.也就是说,我想

for (var x in xs) { ... }
Run Code Online (Sandbox Code Playgroud)

无需空检查即可工作.现在这是我目前所做的,取决于更大的背景:

var xs = f() ?? new X[0];              // when xs is assigned, sometimes
for (var x in xs ?? new X[0]) { ... }  // inline, sometimes
Run Code Online (Sandbox Code Playgroud)

现在,虽然上面对来说完全没问题 - 也就是说,如果创建数组对象有任何"额外开销"我只是不在乎 - 我想知道:

在C#/ .NET中是否存在"空的不可变IEnumerable/IList"单例?(而且,即使没有,是否有一种"更好"的方式来处理上述情况?)

Java具有Collections.EMPTY_LIST不可变的单例 - "良好类型"的通道Collections.emptyList<T>()- 用于此目的,虽然我不确定类似的概念是否甚至可以在C#中工作,因为泛型的处理方式不同.

谢谢.

Sti*_*gar 89

你在找 Enumerable.Empty<int>();

在其他新闻中,Java空列表很糟糕,因为List接口公开了向列表添加元素的方法,这些方法会抛出异常.

  • 因为类方法可能需要返回`List`(可以通过索引访问的集合).那些`List`可以是只读的.有时候你需要返回一个只有零元素的只读`List`.因此,`Collections.emptyList()`方法.您不能只返回一个空的Iterable,因为实现的接口指定该方法返回一个列表.最大的问题是它们不是可以返回的ImmutableList接口..NET中存在同样的问题:任何`IList`都可能是只读的. (30认同)
  • 在旁注中,每个数组都是C#中的IList <associatedType>,当您尝试添加新项时,这将抛出. (6认同)
  • 可能涉及的对象:通常,需要某种列表(而不是“IEnumerable&lt;T&gt;”)的原因是其被具体化的属性(无延迟执行)并具有已知的“Count”。在这种情况下,我们应该使用“IReadOnlyCollection&lt;T&gt;”。如果还需要索引访问,则有“IReadOnlyList&lt;T&gt;”。 (2认同)

Jon*_*Jon 51

Enumerable.Empty<T>() 就是这样.

  • 好吧,不完全是*。:)由于要求使用“列表”,所以“ Array.Empty &lt;T&gt;()”更准确,因为它是“ IList &lt;T&gt;”。它的好处是还可以满足IReadOnlyCollection &lt;T&gt;。当然,只要一个“ IEnumerable &lt;T&gt;”足够了,那么“ Enumerable.Empty &lt;T&gt;()”就非常合适。 (2认同)
  • @Timo这个问题以及包括这个问题在内的许多答案大约是在Array.Empty &lt;T&gt;提供之前的三年编写的。:)无论如何,不​​管标题如何,问题都明确表明,`IEnumerable &lt;T&gt;`可以达到目的。 (2认同)

svi*_*ick 19

我想你在找Enumerable.Empty<T>().

空列表单例没有多大意义,因为列表通常是可变的.


And*_*lon 10

我认为添加扩展方法是一个干净的选择,因为它们能够处理空值 - 如下所示:

  public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> list)
  {
    return list ?? Enumerable.Empty<T>();
  }

  foreach(var x in xs.EmptyIfNull())
  {
    ...
  }
Run Code Online (Sandbox Code Playgroud)


ven*_*eis 9

在原始示例中,您使用一个空数组来提供一个空的可枚举值。虽然使用Enumerable.Empty<T>()是完全正确的,但可能还有其他情况:如果必须使用数组(或IList<T>接口),则可以使用方法

System.Array.Empty<T>()
Run Code Online (Sandbox Code Playgroud)

这可以帮助您避免不必要的分配。

注释/参考: