rspec/rules/S2971/csharp/rule.adoc
Fred Tingaud 16f6c0aecf
Inline adoc when include has no additional value (#1940)
Inline adoc files when they are included exactly once.

Also fix language tags because this inlining gives us better information
on what language the code is written in.
2023-05-25 14:18:12 +02:00

114 lines
4.5 KiB
Plaintext

== Why is this an issue?
In the interests of readability, code that can be simplified should be simplified. To that end, there are several ways ``++IEnumerable++`` language integrated queries (LINQ) can be simplified
* Use ``++OfType++`` instead of using ``++Select++`` with ``++as++`` to type cast elements and then null-checking in a query expression to choose elements based on type.
* Use ``++OfType++`` instead of using ``++Where++`` and the ``++is++`` operator, followed by a cast in a ``++Select++``
* Use an expression in ``++Any++`` instead of ``++Where(element => [expression]).Any()++``.
* Use ``++Count++`` instead of ``++Count()++`` when it's available.
* Don't call ``++ToArray()++`` or ``++ToList()++`` in the middle of a query chain.
Using ``++EntityFramework++`` may require enforcing client evaluations. Such queries should use ``++AsEnumerable()++`` instead of ``++ToArray()++`` or ``++ToList()++`` in the middle of a query chain.
=== Noncompliant code example
[source,csharp]
----
seq1.Select(element => element as T).Any(element => element != null); // Noncompliant; use OfType
seq2.Select(element => element as T).Any(element => element != null && CheckCondition(element)); // Noncompliant; use OfType
seq3.Where(element => element is T).Select(element => element as T); // Noncompliant; use OfType
seq4.Where(element => element is T).Select(element => (T)element); // Noncompliant; use OfType
seq5.Where(element => [expression]).Any(); // Noncompliant; use Any([expression])
var num = seq6.Count(); // Noncompliant
var arr = seq.ToList().ToArray(); //Noncompliant
var count = seq.ToList().Count(x=>[condition]); //Noncompliant
----
=== Compliant solution
[source,csharp]
----
seq1.OfType<T>().Any();
seq2.OfType<T>().Any(element => CheckCondition(element));
seq3.OfType<T>();
seq4.OfType<T>();
seq5.Any(element => [expression])
var num = seq6.Count;
var arr = seq.ToArray();
var count = seq.Count(x=>[condition]);
----
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
* Use "OfType<T>()" here instead.
* Drop "Where" and move the condition into the "Any".
* Drop "ToArray" from the middle of the call chain.
* Replace "ToArray" with "AsEnumerable" in the middle of the call chain.
'''
== Comments And Links
(visible only on this page)
=== on 8 Jun 2015, 08:36:45 Tamas Vajk wrote:
\[~ann.campbell.2] I've changed the description and the code samples of this RSPEC. Can you go through it? Thanks.
=== on 8 Jun 2015, 11:58:09 Ann Campbell wrote:
\[~tamas.vajk] I've made some edits to the description in an attempt to tighten it up a little. Please double-check me.
=== on 8 Jun 2015, 12:10:03 Tamas Vajk wrote:
\[~ann.campbell.2] Thanks, it looks good.
=== on 9 Jun 2015, 14:09:32 Ann Campbell wrote:
see what you think [~tamas.vajk]
=== on 19 Jun 2015, 09:15:08 Tamas Vajk wrote:
\[~ann.campbell.2] The description seems okay now.
But i have a problem with the R# keys. This rule covers quite a lot of R# rules, and I can't put all the code in the field, probably because I reach the max length. :-(
=== on 19 Jun 2015, 13:07:16 Ann Campbell wrote:
\[~tamas.vajk] you are hitting a max length. Fortunately, patterns work here. :-)
See the FindBugs field in RSPEC-2275 for an example.
=== on 8 Jul 2015, 09:04:08 Tamas Vajk wrote:
\[~ann.campbell.2] I've modified the last point as it is not specific to ``++Count++``.
But a now that I'm thinking about it, we will have exceptions to this rule.
In case of ``++seq.ToList().Count(e=> condition)++`` or ``++seq.ToList().Where(e=> condition)++``, it doesn't make sense to call the ``++ToList++``. But ``++seq.ToList().Count()++`` is faster then ``++seq.Count()++`` because internally it uses a single call to the ``++Count++`` property, which is present on a list. (However, in this case we shouldn't use ``++.Count()++``, but ``++.Count++``.)
So we might want to add an additional covered case:
* using ``++.Count()++`` doesn't make sense on ``++IEnumerable++``s that are known to be of a derived type that has the more performant ``++.Count++`` property.
WDYT?
=== on 8 Jul 2015, 14:27:32 Ann Campbell wrote:
I've added the ``++Count()++``/``++Count++`` case.
Do we need to add an exception? If so, I need some help on the wording: under what circumstances is ``++ToList().Count++`` faster? Always? If so, we can just add that "except when..." to the relevant case.
=== on 20 Jul 2015, 12:02:09 Tamas Vajk wrote:
\[~ann.campbell.2] Looks good. We don't need the exception now that we have the additional ``++Count++`` case.
endif::env-github,rspecator-view[]