Summary
When one overload of a member carries [ExcludeFromCodeCoverage] and another overload of the same
name does not, lambdas declared inside the attributed overload remain in the coverage denominator.
This is residual (c) of #457: a deliberate scope choice, recorded so it can be addressed on its own
terms rather than by widening #457.
The #457 presence set is keyed by member name, not by signature. The non-attributed overload
contributes its name to the presence set, the attributed overload's closure resolves to that same
name, and the closure is therefore retained.
Environment
- OS/version: Windows 11 Pro 10.0.26200
- .NET/framework: .NET Framework 4.8.1 (
net481); post-processing runs under PowerShell 7
- Command/flags used:
pwsh -NoProfile -File scripts/vscode/Invoke-MSTestWithCoverage.ps1 -SearchRoot . -Configuration Debug -CoverageOutput "coverage\coverage.cobertura.xml"
- Data source or fixture: any first-party C# type with two same-named overloads where exactly one carries
[ExcludeFromCodeCoverage] and declares a lambda
Steps to Reproduce
- Take a type with two overloads of the same member name. Attribute one with
[ExcludeFromCodeCoverage] and have it declare a lambda; leave the other unattributed.
- Run the coverage pipeline.
- Inspect the post-processed Cobertura report for that file.
- Observe that the attributed overload's closure class survives, because the unattributed overload keeps the shared name in the presence set.
UtilitiesCS.SortEmail is a live instance of the shape: SortAsync appears as four attributed
overloads at UtilitiesCS/EmailIntelligence/EmailParsingSorting/SortEmail.cs:43, 77, 113, 304, and
SaveAttachmentAsync as two at :763, 826.
Expected Behavior
Exemption is resolved per overload, so a lambda inside an attributed overload is excluded even when a
same-named unattributed overload exists.
Actual Behavior
The lambda's lines are retained, because the presence-set key cannot distinguish overloads.
Logs / Screenshots
Impact / Severity
The failure mode is under-exclusion in every case: a file measures no better than it truly is. No
coverage is wrongly deleted, and no gate can be passed that should have failed. Two related keying
dimensions behave correctly and are not affected: two types in the same file sharing a member name are
separated by the declaring-type component of the key, and a partial type spanning files is separated
by the filename component (which also errs toward under-exclusion).
Source
From: docs/features/potential/2026-08-11-overload-name-collision-under-exclusion.md
Summary
When one overload of a member carries
[ExcludeFromCodeCoverage]and another overload of the samename does not, lambdas declared inside the attributed overload remain in the coverage denominator.
This is residual (c) of #457: a deliberate scope choice, recorded so it can be addressed on its own
terms rather than by widening #457.
The #457 presence set is keyed by member name, not by signature. The non-attributed overload
contributes its name to the presence set, the attributed overload's closure resolves to that same
name, and the closure is therefore retained.
Environment
net481); post-processing runs under PowerShell 7pwsh -NoProfile -File scripts/vscode/Invoke-MSTestWithCoverage.ps1 -SearchRoot . -Configuration Debug -CoverageOutput "coverage\coverage.cobertura.xml"[ExcludeFromCodeCoverage]and declares a lambdaSteps to Reproduce
[ExcludeFromCodeCoverage]and have it declare a lambda; leave the other unattributed.UtilitiesCS.SortEmailis a live instance of the shape:SortAsyncappears as four attributedoverloads at
UtilitiesCS/EmailIntelligence/EmailParsingSorting/SortEmail.cs:43, 77, 113, 304, andSaveAttachmentAsyncas two at:763, 826.Expected Behavior
Exemption is resolved per overload, so a lambda inside an attributed overload is excluded even when a
same-named unattributed overload exists.
Actual Behavior
The lambda's lines are retained, because the presence-set key cannot distinguish overloads.
Logs / Screenshots
Get-CoberturaInstrumentedMemberName(
scripts/vscode/Invoke-MSTestWithCoverage.ClosureFilter.ps1), whose presence set is keyed by"$declaringType|$filename"with member names as the set members. The Cobertura<method>element does carry asignatureattribute, but the synthesized closure method name(
<Member>b__N_M) carries no signature information for its declaring member, so the two cannot bejoined on signature from the report alone.
Impact / Severity
The failure mode is under-exclusion in every case: a file measures no better than it truly is. No
coverage is wrongly deleted, and no gate can be passed that should have failed. Two related keying
dimensions behave correctly and are not affected: two types in the same file sharing a member name are
separated by the declaring-type component of the key, and a partial type spanning files is separated
by the filename component (which also errs toward under-exclusion).
Source
From: docs/features/potential/2026-08-11-overload-name-collision-under-exclusion.md