Is there an “Empty List” singleton in C#?

江枫思渺然 提交于 2019-12-02 18:40:43
Stilgar

You are looking for Enumerable.Empty<int>();

In other news the Java empty list sucks because the List interface exposes methods for adding elements to the list which throw exceptions.

Enumerable.Empty<T>() is exactly that.

I think you're looking for Enumerable.Empty<T>().

Empty list singleton doesn't make that much sense, because lists are often mutable.

I think adding an extension method is a clean alternative thanks to their ability to handle nulls - something like:

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

  foreach(var x in xs.EmptyIfNull())
  {
    ...
  }

In your original example you use an empty array to provide an empty enumerable. While using Enumerable.Empty<T>() is perfectly right, there might other cases: if you have to use an array (or the IList<T> interface), you can use the method

System.Array.Empty<T>()

which helps you to avoid unnecessary allocations.

Notes / References:

Microsoft implemented `Any()' like this (source)

public static bool Any<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) throw new ArgumentNullException("source");
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        if (e.MoveNext()) return true;
    }
    return false;
}

If you want to save a call on the call stack, instead of writing an extension method that calls !Any(), just rewrite make these three changes:

public static bool IsEmpty<TSource>(this IEnumerable<TSource> source) //first change (name)
{
    if (source == null) throw new ArgumentNullException("source");
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        if (e.MoveNext()) return false; //second change
    }
    return true; //third change
}
sjb-sjb

Using Enumerable.Empty<T>() with lists has a drawback. If you hand Enumerable.Empty<T> into the list constructor then an array of size 4 is allocated. But if you hand an empty Collection into the list constructor then no allocation occurs. So if you use this solution throughout your code then most likely one of the IEnumerables will be used to construct a list, resulting in unnecessary allocations.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!