-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Enumerable.IsEmpty that judges IEnumerable<T>
is empty.
#28610
Comments
Why not just use |
Nice question! The reason why I think
I think everyone who participates in this issue is familiar to C# and LINQ. But I think that C# beginner is not same. I think C# and .NET core is not for only current C#er. I think |
Thank you for your comment. I think other people have same opinion with you. So I update and add the next answer content on top issue comment. |
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) |
Adding IsEmpty won’t allow you to iterate over the items. It will have the same issue as Any() and Count(). Any time you read from an IEnumerable, that’s it—you can’t enumerate it again. That includes Any and Count, and it would also include IsEmpty. Your argument is that adding IsEmpty would make correct usage clearer than Any, but your usage of Any is incorrect in the same way as your example of Count. If IsEmpty gives you the impression that you can reuse the IEnumerable, then it’s misleading.
Maybe, or maybe not. Maybe it skips the first line, maybe it throws an exception. It might work, but that’s not guaranteed. |
@Zenexer I don't understand what you're saying. Do you mean IEnumerator<T>? If that's the case, yes it is supposed to be used once. but still, you can call GetEnumerator() on IEnumerable<T> as many times as you want to get a new one? Example: using System;
using System.Collections.Generic;
namespace ConsoleApp10 //:^)
{
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
WriteAllIfNotEmpty(list);
}
public static void WriteAllIfNotEmpty<T>(IEnumerable<T> enumerable)
{
if (!enumerable.IsEmpty()) //Using the enumerable
{
foreach (T item in enumerable)
{
Console.WriteLine(item);
//Would it really work here, given that I've used enumerable already?
}
}
else
Console.WriteLine("Oops, empty");
}
}
static class Extensions
{
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
if (enumerable is null) throw new ArgumentNullException(nameof(enumerable));
using (IEnumerator<T> enumerator = enumerable.GetEnumerator())
return !enumerator.MoveNext();
}
}
} Outputs:
|
In my opinion this would help beginners a lot. I often see |
This seems to be a duplicate suggestion of #27661 albeit with a different name. |
@RyotaMurohoshi You are right. The problem with DataObject.count() == 0 is that when DataObject is NULL Then it will throw exception. As i know we can handle it with this way DataObject?.count() which will not throw exception. but in my openion DataObject.IsEmpty() is more straight forward for checking. |
@kashifasif Although it is an extension method (therefore legal to call on |
Hi @vcsjones !
in #27661,
I think The reasons why I think so are
My suggestion method is that checks |
Sorry, in my opinion, this method should throw @Gnbrkm41 Thank you! |
I believe parameter-less variant of None method could be added as well if the Predicate one were to be added, but in the issue above (#32878) (@)stephentoub mentioned that it adds little value while it has some downsides.
I especially agree to the last point of not being able to write compatible library with lower versions of .NET Standard. |
In my suggestion, the name of In some other programming languages, there are methods that judges array, list, sequence, enumerable are empty or not. And, the names are I think the By the way, I agree this (@)stephentoub's this comment. It is so important! But in my opinion, I think everyone who participates in this issue is know how to use How do you think about viewpoint from C# beginner? I want to listen your and others opinion. |
Summary of things so far: Pros
Cons
|
That sounds wrong to me. We have |
If we are going to have an (Yes, I know this contradicts my last comment.) |
There's no guarantee that subsequent calls to GetEnumerator will succeed. It usually works, but that's not always the case. It may also have unintended side effects. Typically, static analyzers like ReSharper will yell at you if you reuse an IEnumerable. (If you use a more specific type like IList for which GetEnumerator can be called multiple times, you won't get the warning.) The bigger point here, though, is that @RyotaMurohoshi makes the argument that |
@Zenexer Ah, I see now. Never thought of that. |
@Zenexer OK, I see now. And I checked that how does Rider tell us this point. |
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. |
Yes. I agreen above.
But sorry, I don't agree above point. And at the issue, (@)terrajobst does not talk |
It may be so valuable to talk about it. I think next points and ideas. First. https://docs.microsoft.com/en-us/dotnet/api/system.string.isnullorempty?view=netcore-1.0 Second. (Sorry I do not know it, but it may exist in BCL/FCL.) Third.
POINT! They are extension methods for Nullable types. https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/is-null-or-empty.html Forth. C# 8.0 will add and improve language features around
But in my opinion, I want to wait talking about it until C# 8.0 release and do not want to talk in this issue. |
@cston Thank you! |
Just wanted to mention that Enumerables are a form of generator. By definition they cannot be empty, but you can check if they produce/generate anything. I could see For correctness sake, don't conflate generators and collections. /opinion |
@bcronce IEnumerable makes no assertions about where the data is coming from—it could be a generator, it could be a collection, or it could be something else entirely. Not only does it make no sense for IEnumerable to provide IsEmpty, it has no way of doing so because that test can’t be performed for many of the types that implement IEnumerable (particularly generators, as you mentioned). This is rarely clear to newcomers, and I consider it a documentation/education issue. I’m not really sure how to improve the situation, but we need to find a better way of communicating the role the IEnumerable plays. It has a tendency to confuse both new programmers and experienced programmers alike. It’s an incredibly powerful tool, but it’s not particularly intuitive. |
Closing as dup of https://github.com/dotnet/corefx/issues/32878 |
Edit: Never mind, I confused the OP with another commenter. |
Summary
Add
IsEmpty
method.IEnumerable<T>
is empty.IEnumerable<T>
extension method. NewLINQ to Objects member
.IsEmpty
method helps them.API
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 thatenumerable
is empty than!enumerable.Any()
.!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 thinkIsEmpty
is so easy to find and useful to them.Background
There are no method or property to judge that Array,
IEnumerable<T>
andList<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. Iftarget.txt
is huge, it is so bad.Good practice is to use
Any
method and!
to judgeis empty
. This can judge that file is empty or not without reading all lines.By the way, I do NOT think this is BEST way.
Solution and Usage
I suggest
IsEmpty
method toIEnumerable<T>
as extension method.IsEmpty
judeges that Array,IEnumerable<T>
andList<T>
etc are empty or not.This is more clear and explicit than
Any
and!
usage. And beginner can notice theIsEmpty
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
orisEmpty
methods.F#
https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/list.isempty%5B't%5D-function-%5Bfsharp%5D
https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/array.isempty%5b't%5d-function-%5bfsharp%5d
https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/seq.isempty%5b't%5d-function-%5bfsharp%5d
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()?
The text was updated successfully, but these errors were encountered: