Simplify LINQ Expression for .Any()

Hi

R# is suggesting me to "simplify" my LINQ Expression from !myList.Any(x => x.Id == id) to myList.All(x => x.Id != id).
I believe that that's not a good suggestion because .Any can perform faster than .All because it will stop as soon as the expression is true and All will always perform the whole List.

Your thoughts?
Giuseppe

8 comments
Comment actions Permalink

All will also short-circuit and stop evaluation when it meets a predicate that returns false. In this instance, the two expressions are equivalent.

  • Assuming the sequence contains only items with the required id, the Any expression will exit after the first item, returning true. The All expression will also exit after the first item, since the first item fails the predicate, it knows that not all items match, so can return false.
  • If the sequence contains just one item of the require id, the Any expression will iterate until it finds it, and returns true. The All expression will continuning iterating while it can't find it, and return as soon as it does.
  • If the id isn't in the sequence, the Any expression will iterate all items (since none match the predicate) and return false. The All expression will also iterate all items (since every item matches the predicate) but return true.


In all instances, the sequence is iterated the same number of times.

Hope this helps
Matt

1
Comment actions Permalink

I do agree that, for performance, there is no difference between

bool needToWait = !apples.Any(apple => apple.Color == "green")

 
(there isn't any apple that is green)


and

bool needToWait = apples.All(apple => apple.Color != "green")
(every apple is not green)

HOWEVER

The result of the first notation is much more predictable for empty collections.
EmptyCollection.Any(AnyCondition) always evaluates to false, as you would expect.
EmptyCollection.All(AnyCondition) always evaluates to true, but this is less intuitive.

It's closer to the way you speak: you use "all" or "not any".
Nobody really says "every apple is not green"

SO

I'd like to be able to disable (or even invert!) this special case of simplying LINQ expressons. But if I disable the general rule, do I also disable other simplification suggestions?

0
Comment actions Permalink

However I would say "all my apples are not green" and am less likely to say "there are not any of my apples that are green"

1
Comment actions Permalink

I have noticed that using `All` with `!=` generates very bad SQL in Linq2Sql compared to using `!Any`.

Using All with !=

SELECT ...
FROM [dbo].[tblCategoryType] AS [t0]
WHERE NOT (EXISTS(
   SELECT NULL AS [EMPTY]
   FROM [dbo].[tblClassToLevels] AS [t1]
   WHERE (
      (CASE
         WHEN [t1].[fkClassCatID] <> ([t0].[categoryTypeID]) THEN 1
         ELSE 0
      END)) = 0
))
GO

Using !Any

SELECT ...
FROM [dbo].[tblCategoryType] AS [t0]
WHERE NOT (EXISTS(
   SELECT NULL AS [EMPTY]
   FROM [dbo].[tblClassToLevels] AS [t1]
   WHERE [t1].[fkClassCatID] = ([t0].[categoryTypeID])
))

 The execution plan from these two are very different and the All with != is much worse.

2
Comment actions Permalink

I was also annoyed by this "simplification" which in my opinion is really an obfuscation. Simply minimizing the number of operators is not always a good idea. Unfortunately I had to change this one into a hint which is less than ideal because it does suggest very useful refactorings in other cases. I hope you can find a way to improve this refactoring in the future.

1
Comment actions Permalink

Time is ticking away, but R# developer's are not in a hurry to disable this wrong "simplification". Please, do it! Or, maybe you can make additional option especially for this case? 

I oppose such simplification. And I'm not alone in this request. 

Thank you in advance.

1
Comment actions Permalink

Hello everyone! 

 

Please refer to the corresponding issue reported in YouTrack - https://youtrack.jetbrains.com/issue/RSRP-328381.

You are welcome to comment or vote for it.

Thank you.

 

0
Comment actions Permalink

Angelina, that case has been around since 2012 - why would people bother to comment on it when it's clearly being ignored?

0

Please sign in to leave a comment.