Is there an "Empty List" singleton in C#?

C#SingletonIenumerableEmpty List

C# Problem Overview


In C# I use LINQ and IEnumerable a good bit. And all is well-and-good (or at least mostly so).

However, in many cases I find myself that I need an empty IEnumerable<X> as a default. That is, I would like

for (var x in xs) { ... }

to work without needing a null-check. Now this is what I currently do, depending upon the larger context:

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

Now, while the above is perfectly fine for me -- that is, if there is any "extra overhead" with creating the array object I just don't care -- I was wondering:

Is there "empty immutable IEnumerable/IList" singleton in C#/.NET? (And, even if not, is there a "better" way to handle the case described above?)

Java has Collections.EMPTY_LIST immutable singleton -- "well-typed" via Collections.emptyList<T>() -- which serves this purpose, although I am not sure if a similar concept could even work in C# because generics are handled differently.

Thanks.

C# Solutions


Solution 1 - C#

You are looking for Enumerable.Empty<T>().

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

Solution 2 - C#

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

Solution 3 - C#

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

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

Solution 4 - C#

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:

Solution 5 - C#

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())
  {
    ...
  }

Solution 6 - C#

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.

Solution 7 - C#

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
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser166390View Question on Stackoverflow
Solution 1 - C#StilgarView Answer on Stackoverflow
Solution 2 - C#JonView Answer on Stackoverflow
Solution 3 - C#svickView Answer on Stackoverflow
Solution 4 - C#ventiseisView Answer on Stackoverflow
Solution 5 - C#Andrew HanlonView Answer on Stackoverflow
Solution 6 - C#sjb-sjbView Answer on Stackoverflow
Solution 7 - C#user2023861View Answer on Stackoverflow