Repository navigation
SA1130: report anonymous methods whose parameter names differ from the delegate's - #4179
Merged
Merged
Conversation
… differ from the delegate's
To check that a lambda binds to the same method, the analyzer built the lambda
from the delegate's parameter list instead of the anonymous method's own. When
the names differed, e.g. list.Select(delegate (int x) { return x; }), the body
no longer bound, the speculative binding failed, and nothing was reported. An
anonymous method with a parameter list now uses its own list; the delegate's
list is only used when the anonymous method has no parameter list.
These newly reported cases exposed two code fix problems, which are also fixed:
- Removing the parameter types could make a call ambiguous between overloads
taking delegates with different parameter types. The code fix now keeps the
types when the call wouldn't bind to the same method without them.
- An anonymous method with ref or out parameters was left unchanged by the
code fix. It now becomes a lambda with explicit parameter types and modifiers.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4179 +/- ##
========================================
Coverage 97.50% 97.50%
========================================
Files 1236 1236
Lines 131895 132077 +182
Branches 4276 4279 +3
========================================
+ Hits 128602 128780 +178
- Misses 2153 2157 +4
Partials 1140 1140 🚀 New features to boost your workflow:
|
AArnott
marked this pull request as ready for review
October 8, 2026 20:37
This was referenced Nov 11, 2026
Bump StyleCop.Analyzers from 1.2.0-beta.556 to 1.3.180
microsoftgraph/aspnetcore-webhooks-sample#436
Open
Open
This was referenced Nov 13, 2026
Open
Open
Merged
Open
Bump StyleCop.Analyzers from 1.2.0-beta.556 to 1.3.180
microsoftgraph/msgraph-sample-aspnet-core#256
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SA1130 never reported an anonymous method passed as an argument if its parameter names differed from the delegate's parameter names. For example,
list.Select(delegate (int x) { return x; })was never reported.Cause
To make sure the lambda binds to the same overload, the analyzer speculatively binds the call with a lambda in place of the anonymous method. It built that lambda from the delegate's parameter list (
argforFunc<T, TResult>) instead of the anonymous method's own list. When the names differed, the body (return x;) didn't bind, the speculative binding failed, and nothing was reported. The existing testTestAnonymousMethodInferringTypeArgumentAsyncnames its parameterargto work around this, and its doc comment says so.Fix
delegate { }with no parameter list, which can't become a parameterless lambda.Overloaded(delegate (int value) { return 0; })withFunc<int,int>/Func<string,int>overloads becameOverloaded(value => { return 0; })(CS0121). The fix now keeps the types when the call wouldn't bind to the same method without them.ref/outparameters was reported, but the code fix did nothing. It now produces(ref int x) => { ... }.SA1130.mdnow says when the code fix keeps parameter names and types.Coordination with #4133 and #4147
This branches from current master, which already has both:
list.Select(delegate (int x) { ... })becomeslist.Select((int x) => { ... }).GetDelegateParameterList.GetDelegateParameterListis now only called for anonymous methods without a parameter list. Its params collection handling from #4147 still applies there, and theTestParamsAsynccases pass.Behavior changes
SA1130 now reports anonymous methods passed as arguments (to methods, constructors and indexers) whose parameter names differ from the delegate's, e.g.
list.Select(delegate (int x) { return x; }),Single(delegate (int value) { return value; })andMultiple(delegate (int first, string second) { }). Existing code that uses this pattern will get new SA1130 warnings. All of them have a working code fix.Tests
Added to
SA1130UnitTests, so they run in every language version's project:TestAnonymousMethodWithDifferentParameterNamesAsync: methods, multiple parameters, a constructor and an indexer. The fix givesvalue => ...and(first, second) => ....TestAnonymousMethodWithDifferentParameterNamesPassedToLinqAsync:list.Select(delegate (int x) ...)becomeslist.Select((int x) => ...).TestAnonymousMethodWithOverloadsDifferingInParameterTypesAsync: the types are kept to avoid ambiguity.TestAnonymousMethodWithRefAndOutParametersAsync.All SA1130 tests pass locally in the C# 6, 7, 10, 13 and 15 projects (Linux, net6.0).