Skip to content

C#: Missed FirstOrDefault query. - #22497

Draft
michaelnebel wants to merge 9 commits into
github:mainfrom
michaelnebel:feat/csharp-missed-firstordefault-opprtunity
Draft

C#: Missed FirstOrDefault query.#22497
michaelnebel wants to merge 9 commits into
github:mainfrom
michaelnebel:feat/csharp-missed-firstordefault-opprtunity

Conversation

@michaelnebel

Copy link
Copy Markdown
Contributor

No description provided.

@github-actions

Copy link
Copy Markdown
Contributor

QHelp previews:

csharp/ql/src/Linq/MissedFirstOrDefaultOpportunity.qhelp

Missed opportunity to use FirstOrDefault

Programmers sometimes search a sequence by iterating over each element, testing it, and returning the first element that satisfies the test. If the loop completes without finding a match, the method then returns a default value such as null or default.

Recommendation

This pattern is directly available as the FirstOrDefault method in LINQ. Using the library method makes the search intent explicit and avoids manually spelling out the loop and fallback return.

Example

In this example the method searches a list of operations for the first operation with a matching identifier, returning null if no match is found.

usingSystem;usingSystem.Collections.Generic;classMissedFirstOrDefaultOpportunity{publicstaticOperationFindOperation(IEnumerable<Operation>operations,stringoperationId){foreach(varoperationinoperations){if(string.Equals(operation.OperationId,operationId,StringComparison.Ordinal))returnoperation;}returnnull;}}classOperation{publicstringOperationId{get;set;}}

The LINQ FirstOrDefault method can express this search more directly.

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;classMissedFirstOrDefaultOpportunityFix{publicstaticOperationFindOperation(IEnumerable<Operation>operations,stringoperationId){returnoperations.FirstOrDefault(operation =>string.Equals(operation.OperationId,operationId,StringComparison.Ordinal));}}

The following examples should not use FirstOrDefault, because they do more than return the matching element or because the fallback value is not the default value.

usingSystem;usingSystem.Collections.Generic;classMissedFirstOrDefaultOpportunityGood{publicstaticOperationFindOperationOrThrow(IEnumerable<Operation>operations,stringoperationId){foreach(varoperationinoperations){if(string.Equals(operation.OperationId,operationId,StringComparison.Ordinal))thrownewInvalidOperationException("Unexpected operation.");}returnnull;}publicstaticOperationFindReplacementOperation(IEnumerable<Operation>operations,stringoperationId){foreach(varoperationinoperations){if(string.Equals(operation.OperationId,operationId,StringComparison.Ordinal))returnoperation;}returnnewOperation();}publicstaticstringFindOperationId(IEnumerable<Operation>operations,stringoperationId){foreach(varoperationinoperations){if(string.Equals(operation.OperationId,operationId,StringComparison.Ordinal))returnoperation.OperationId;}returnnull;}}

References

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelnebel@baywet