From 0e1f56b4f0aaed9be97c4eb1a1be195aa4c72522 Mon Sep 17 00:00:00 2001 From: Vianney de Bellabre Date: Mon, 17 Jun 2024 16:01:15 +0200 Subject: [PATCH] [EC91] [C#] Use Where before OrderBy (#341) --- CHANGELOG.md | 1 + RULES.md | 1 + .../src/main/rules/EC91/EC91.json | 16 +++ .../src/main/rules/EC91/csharp/EC91.asciidoc | 101 ++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 ecocode-rules-specifications/src/main/rules/EC91/EC91.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC91/csharp/EC91.asciidoc diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bc2e03c..a04f56e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [C# #54](https://github.com/green-code-initiative/ecoCode-csharp/pull/54) [EC92] [C#] Use string.Length instead of comparison with empty string +- [C# #61](https://github.com/green-code-initiative/ecoCode-csharp/issues/61) [EC91] [C#] Use Where before OrderBy ### Changed diff --git a/RULES.md b/RULES.md index 1b2b7ab7..9bba37f3 100644 --- a/RULES.md +++ b/RULES.md @@ -66,6 +66,7 @@ Some are applicable for different technologies. | EC87 | Use collection indexer | Collection indexers should be used instead of Linq, when available | | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | βœ… | 🚫 | | EC88 | Dispose resource asynchronously | Resources that implement `IAsyncDisposable` should be disposed asynchronously | | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | βœ… | 🚫 | | EC89 | Avoid using function cache without limit | If a function has decorators without max size cache, the program will store unlimited data | | ❓ | ❓ | ❓ | βœ… | ❓ | ❓ | ❓ | +| EC91 | Use `Where` before `OrderBy` | Filter elements before sorting them for improved efficiency | | ❓ | ❓ | ❓ | ❓ | ❓ | βœ… | ❓ | | EC92 | Use string.Length instead of comparison with empty string | Comparing a string to an empty string is unnecessary and can be replaced by a call to `string.Length` which is more performant and more readable. | | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | βœ… | 🚫 | | EC93 | Return `Task` directly | Consider returning a `Task` directly instead of a single `await` | | ❓ | ❓ | ❓ | ❓ | ❓ | βœ… | ❓ | | EC94 | Use orElseGet instead of orElse | Parameter of orElse() is evaluated, even when having a non-empty Optional. Supplier method of orElseGet passed as an argument is only executed when an Optional value isn’t present. Therefore, using orElseGet() will save computing time. | [cnumr best practices (3rd edition) BP_042](https://github.com/cnumr/best-practices/blob/main/chapters/BP_042_fr.md) | 🚧 | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | diff --git a/ecocode-rules-specifications/src/main/rules/EC91/EC91.json b/ecocode-rules-specifications/src/main/rules/EC91/EC91.json new file mode 100644 index 00000000..25392145 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC91/EC91.json @@ -0,0 +1,16 @@ +{ + "title": "Use Where before OrderBy", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "ecocode", + "performance", + "bad-practice" + ], + "defaultSeverity": "Major" +} \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC91/csharp/EC91.asciidoc b/ecocode-rules-specifications/src/main/rules/EC91/csharp/EC91.asciidoc new file mode 100644 index 00000000..cc6053d5 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC91/csharp/EC91.asciidoc @@ -0,0 +1,101 @@ +:!sectids: + +Use Where before OrderBy. + +## Why is this an issue ? + +When `Orderby` is called right before `Where`, LINQ sorts all the elements before filtering them. Doing the opposite is more efficient, first filter the items then sort the remaining ones only. + +### When can it be ignored ? + +This rule shouldn't be ignored. + +## Non-compliant examples + +[source, cs] +---- +public static async Task Test() +{ + var query = items + .OrderBy(x => x) + .Where(x => x > 10); +} +---- + +[source, cs] +---- +public static async Task Test() +{ + var query = items + .OrderBy(x => x) + .ThenByDescending(x => x) + .Where(x => x > 10); +} +---- + +[source, cs] +---- +public static async Task Test() +{ + var query = from item in items + orderby item + where item > 10 + select item; +} +---- + +[source, cs] +---- +public static async Task Test() +{ + var query = from item in items + orderby item descending + where item > 10 + select item; +} +---- + +## Compliant examples + +[source, cs] +---- +public static async Task Test() +{ + var query = items + .Where(x => x > 10) + .OrderBy(x => x); +} +---- + +[source, cs] +---- +public static async Task Test() +{ + var query = items + .Where(x => x > 10) + .OrderBy(x => x) + .ThenByDescending(x => x); +} +---- + +[source, cs] +---- +public static async Task Test() +{ + var query = from item in items + where item > 10 + orderby item + select item; +} +---- + +[source, cs] +---- +public static async Task Test() +{ + var query = from item in items + where item > 10 + orderby item descending + select item; +} +---- \ No newline at end of file