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
Please sign in to leave a comment.
All will also short-circuit and stop evaluation when it meets a predicate that returns false. In this instance, the two expressions are equivalent.
In all instances, the sequence is iterated the same number of times.
Hope this helps
Matt
I do agree that, for performance, there is no difference between
bool needToWait = !apples.Any(apple => apple.Color == "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?
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"
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.
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.
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.
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.
Angelina, that case has been around since 2012 - why would people bother to comment on it when it's clearly being ignored?