From standard created by tbrettallen : dotnet/standard#509
For the sake of code clarity, my team uses an IEnumerable extension method None instead of !Any().
Currently our implementation is:
public static bool None<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return !source.Any<TSource>(predicate);
}
While it might be superfluous, ReSharper and other code analytics tools don't recognize this when analyzing LINQ statements. For example, it has many times suggested changing All(x => x.y != z) into !Any(x => x.y == z).
I feel this would be a simple to implement standard method for the IEnumerable interface and allow for easier to read code.
@cston, @333fred PTAL.
Then there should be Some as well :)
C#
public static bool Some<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return !source.All<TSource>(predicate);
}
@omariom - Probably can't call it Some? I feel like I want that method to have the same behavior as Any.
The name would have to be OnlySome which isn't really clearer than NotAll.
I think the point was that None() is easier to read that !Any().
Some() would be identical to Any(), no?
Some() would mean Any(). OnlySome() would mean !All() which is what @omariom was after to complete the square (Any, All, NotAny, NotAll). As in, "only some of these objects are red." I'm not sure it's any clearer than !All(), particularly when none (not some) are red.
I understand the original reasoning, but I don't think we should be in the business of adding new APIs that are effectively just differently-named forwarders to existing APIs. They add very little value and could be done by any developer in any library with as good an implementation as the core libraries can provide. While adding little value without downsides is something to consider, there are downsides here: additional surface area a developer needs to learn, potential confusion as to when to use None vs !Any, inability to write code to a lower .NET Standard version when such a lower version could easily targeted by using the existing named API, etc.
If the BCL ever adds Optional<>, Optional<>.None would be more like Enumerable.Empty<> than like IEnumerable<>.None. Even though the name is the same.
We have .Any with and without a predicate. So we should have .None with and without a predicate.
Personally, I would probably use .None() more often than .None(bool).
They add very little value and could be done by any developer in any library with as good an implementation as the core libraries can provide.
The value is clarity of intent. Consider this example:
var b1 = !dataSource.Root.Child[0].Grandchildern.Any(x => x ^ 2 > 3);
var b2 = dataSource.Root.Child[0].Grandchildern.None(x => x ^ 2 > 3);
With b1 it is really easy to miss that not operator. It is meant to apply to the Any operation, but it is all the way over on the other side of the expression chain.
This is such a common issue that every project I've joined since LINQ was created has a None extension method, and often more than one.
Thank you for the suggestion, but we're not going to proceed with this. While the existing naming may not be to everyone's liking, this suggestion and variations of it are all accomplishable with Any, All, !Any, and !All. The benefit to adding additional method that exist just to provide different names doesn't outweigh the costs, both to the implementers/maintainers of that functionality and to consumers now having to see/learn about the increased surface area.
Most helpful comment
I understand the original reasoning, but I don't think we should be in the business of adding new APIs that are effectively just differently-named forwarders to existing APIs. They add very little value and could be done by any developer in any library with as good an implementation as the core libraries can provide. While adding little value without downsides is something to consider, there are downsides here: additional surface area a developer needs to learn, potential confusion as to when to use None vs !Any, inability to write code to a lower .NET Standard version when such a lower version could easily targeted by using the existing named API, etc.