runtime: Add Enumerable.IsEmpty that judges `IEnumerable` is empty.

Summary

Add IsEmpty method.

  • Judges that IEnumerable<T> is empty.
  • IEnumerable<T> extension method. New LINQ to Objects member.
  • Someone uses “Count() == 0” incorrectly. IsEmpty method helps them.

API

public static class Enumerable
{
    public static bool IsEmpty<TSource>(this IEnumerable<TSource> source);
}

Discussion [UPADTED]

How about use !enumrable.Any()?

I think enumerable.IsEmpty() is better than !enumerable.Any() with next reasons.

  • IsEmpty() is more clear and more explicit to check that enumerable is empty than !enumerable.Any().
  • For C# beginner, !enumerable.Any() to check empty is not familiar, not clear and not easy to find.

I think everyone who participates in this issue is familiar to C# and LINQ. So we know how to use !enumerable.Any() and reason to use !enumerable.Any().

But I think that C# beginner is not same. Please imagine C# beginner. It is a little difficult to find usage of !enumerable.Any() to check empty for them. I think IsEmpty is so easy to find and useful to them.

Background

There are no method or property to judge that Array, IEnumerable<T> and List<T> etc are empty or not.

Someone uses “Count() == 0” incorrectly to judge that IEnumerable<T> is empty or not. This is bad usage. Next code is an example.

Next code read all line twice. To judge target.txt is empty, we do not need read all lines. If target.txt is huge, it is so bad.

IEnumerable<string> lines = File.ReadLines("target.txt");
// Bad solution
if(lines.Count() == 0) {
    Console.WriteLine("target.txt is empty.");
    return ;
}

// iterate all line and use it.

Good practice is to use Any method and ! to judge is empty. This can judge that file is empty or not without reading all lines.

IEnumerable<string> lines = File.ReadLines("target.txt");
// Current good solution
if(!lines.Any()) {
    Console.WriteLine("target.txt is empty.");
    return ;
}

// iterate all line and use it.

By the way, I do NOT think this is BEST way.

Solution and Usage

I suggest IsEmpty method to IEnumerable<T> as extension method. IsEmpty judeges that Array, IEnumerable<T> and List<T> etc are empty or not.

IEnumerable<string> lines = File.ReadLines("target.txt");
if(lines.IsEmpty()) {
    Console.WriteLine("target.txt is empty.");
    return ;
}

// iterate all line and use it.

This is more clear and explicit than Any and ! usage. And beginner can notice the IsEmpty method with IntelliSense.

Relatives

There is IsEmpty method in Ix.NET.

Ix.NET

https://github.com/dotnet/reactive/blob/master/Ix.NET/Source/System.Interactive/Empty.cs

Next languages have IsEmpty or isEmpty methods.

F# https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/list.isempty['t]-function-[fsharp] https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.isempty['t]-function-[fsharp] https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/seq.isempty['t]-function-[fsharp]

Java https://docs.oracle.com/javase/10/docs/api/java/util/Collection.html#isEmpty()

Kotlin https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/is-empty.html https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-collection/is-empty.html

Scala https://www.scala-lang.org/api/current/scala/collection/GenTraversableOnce.html#isEmpty:Boolean

Update

Add Discussion : How about use !enumrable.Any()?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 29 (14 by maintainers)

Most upvoted comments

Why not just use !enumerable.Any()

Summary of things so far:

Pros

  • Increases the terseness of the code, Extremely straightforward to understand and use unlike !Any() (Thus making it beginner-friendly)
  • Once added, can be used for all types that implement IEnumerable<T>

Cons

  • Essentially a renaming of !Any(), does not add a massive value
  • Would limit the portability of the code that uses this, as it is not present in older standards/frameworks (if it were to be added)
  • Requires boxing of enumerator in some cases (List.Enumerator, Dictionary.Enumerator etc…) - Isn’t a problem limited to IsEmpty, common problem of all LINQ extensions but perhaps a thing to consider if it’s expected to be used with List<T>, Dictionary<TKey, TValue> etc frequently

@kashifasif IEnumerable.Empty is not the same as null; the suggested problem with Count() is that it actually has to enumerate through the enumerable to count how many items are in the enumerable, which is unnecessary if we just want to check if the enumerable is empty or not. (imagine the resource wasted to enumerate through 2^31-1 items, when what we really need to know is if there’s more than one item or not)

Although it is an extension method (therefore legal to call on (IEnumerable<T>)null, unlike instance methods), I think it should not replace the null check and explicit null check (enumerable is null) must be used.

In my opinion this would help beginners a lot. I often see Count() == 0 and people don’t really learn to use Any until an analyzer tells them

Just to clarify, I do agree with you, @RyotaMurohoshi: the current system isn’t intuitive, and this confusion over multiple enumeration just serves to exemplify that. I don’t have an easy solution, unfortunately, but it goes beyond a simple lack of IsEmpty().

This is moving a bit away from the issue at hand, but perhaps someday we’ll see an attribute that can mark IEnumerables at multi-enumeration-safe. The catch there is that it’s not always clear when multiple enumeration is safe: sometimes it will work but have a performance penalty, such as with Entity Framework Core. While multiple enumeration with EF Core is technically possible (and sometimes desirable), it’s often more efficient to cache everything in a list.

Any() and its overloads seem to be more versatile than IsEmpty (if there was one) method, though I do agree that IsEmpty would be much simpler and easier to understand/read.

Has there been any case where a new method was added in BCL/FCL that simply call other methods for clarity’s sake? (Basically renaming an existing one)