Skip to content

fix: preserve ref/out/in modifiers when raising events with by-ref delegates#719

Merged
vbreuss merged 1 commit into
mainfrom
preserve-ref/out/in-modifiers
Apr 29, 2026
Merged

fix: preserve ref/out/in modifiers when raising events with by-ref delegates#719
vbreuss merged 1 commit into
mainfrom
preserve-ref/out/in-modifiers

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented Apr 29, 2026

This pull request improves the code generation logic for event delegates with by-ref parameters (ref, out, in, and ref readonly) in the mock class source generator. The changes ensure that parameter modifiers are preserved in both method declarations and invocations, and that definite assignment requirements for out parameters are satisfied, preventing potential compiler errors. Additionally, a new test verifies correct behavior for events with ref and out delegate parameters.

Code generation improvements for by-ref parameters:

  • Updated FormatParametersWithTypeAndName and FormatParametersAsNames to preserve ref, out, and in modifiers, ensuring generated method signatures and invocations match the original delegate signatures. Introduced the helper method RefKindKeyword for cleaner modifier handling.
  • In the mock event raise implementation, added logic to pre-assign default values to out parameters when there are no subscribers, ensuring definite assignment as required by the compiler.
  • Modified argument generation for delegate invocations to bind by-ref arguments to local variables with default values, ensuring addressable storage and correct modifier usage.

@vbreuss vbreuss self-assigned this Apr 29, 2026
@vbreuss vbreuss added the bug Something isn't working label Apr 29, 2026
@vbreuss vbreuss enabled auto-merge (squash) April 29, 2026 17:57
@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

Test Results

    21 files  ±0      21 suites  ±0   17m 32s ⏱️ + 9m 24s
 3 845 tests +1   3 844 ✅ +1  1 💤 ±0  0 ❌ ±0 
25 049 runs  +3  25 048 ✅ +3  1 💤 ±0  0 ❌ ±0 

Results for commit 493cdb4. ± Comparison against base commit ddd61e7.

@vbreuss vbreuss merged commit 22dfeb1 into main Apr 29, 2026
16 checks passed
@vbreuss vbreuss deleted the preserve-ref/out/in-modifiers branch April 29, 2026 18:08
@github-actions
Copy link
Copy Markdown

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Method Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Event_Mockolate 399.3 ns 3.83 ns 3.19 ns 1.00 0.01 0.1254 0.0005 2.05 KB 1.00
Event_Moq 13,961.5 ns 107.87 ns 90.07 ns 34.96 0.35 0.7324 - 12.51 KB 6.09
Event_NSubstitute 5,330.1 ns 62.07 ns 48.46 ns 13.35 0.16 0.5493 0.0076 9.05 KB 4.40
Event_FakeItEasy 230,636.0 ns 2,224.41 ns 2,080.71 ns 577.60 6.74 0.7324 0.4883 15.39 KB 7.49
Event_Imposter 1,384.3 ns 26.17 ns 24.48 ns 3.47 0.07 0.5379 0.0153 8.8 KB 4.29
Event_TUnitMocks 180.7 ns 2.87 ns 2.54 ns 0.45 0.01 0.0837 0.0002 1.37 KB 0.67
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.61GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Method N Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Indexer_Mockolate 1 988.9 ns 16.93 ns 15.84 ns 1.00 0.02 0.2460 0.0019 4.03 KB 1.00
Indexer_Moq 1 216,854.2 ns 1,884.60 ns 1,670.65 ns 219.35 3.75 0.9766 0.4883 20.48 KB 5.08
Indexer_NSubstitute 1 9,922.8 ns 79.01 ns 73.90 ns 10.04 0.17 0.7782 - 12.78 KB 3.17
Indexer_FakeItEasy 1 12,276.8 ns 43.32 ns 38.40 ns 12.42 0.19 0.8392 0.0305 13.88 KB 3.44
Indexer_Imposter 1 1,097.7 ns 18.01 ns 16.84 ns 1.11 0.02 0.3147 0.0038 5.16 KB 1.28
Indexer_Mockolate 10 2,714.8 ns 20.52 ns 19.20 ns 1.00 0.01 0.3090 - 5.09 KB 1.00
Indexer_Moq 10 230,596.5 ns 1,134.16 ns 1,060.90 ns 84.95 0.70 1.7090 1.4648 30 KB 5.90
Indexer_NSubstitute 10 24,236.5 ns 44.37 ns 41.50 ns 8.93 0.06 1.5564 0.0305 25.58 KB 5.03
Indexer_FakeItEasy 10 26,485.2 ns 147.23 ns 137.72 ns 9.76 0.08 2.1667 0.0610 35.47 KB 6.97
Indexer_Imposter 10 2,475.1 ns 32.00 ns 29.93 ns 0.91 0.01 0.4845 0.0076 7.97 KB 1.57
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 3.12GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Method N Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Method_Mockolate 1 431.3 ns 3.29 ns 2.75 ns 1.00 0.01 0.1416 0.0010 2.32 KB 1.00
Method_Moq 1 180,290.9 ns 407.15 ns 339.99 ns 418.00 2.67 0.4883 - 14.58 KB 6.28
Method_NSubstitute 1 5,512.2 ns 28.04 ns 24.86 ns 12.78 0.10 0.5569 0.0076 9.12 KB 3.93
Method_FakeItEasy 1 6,165.3 ns 27.52 ns 25.74 ns 14.29 0.10 0.4959 - 8.11 KB 3.50
Method_Imposter 1 561.6 ns 5.07 ns 4.50 ns 1.30 0.01 0.2470 0.0029 4.04 KB 1.74
Method_TUnitMocks 1 670.1 ns 2.53 ns 2.37 ns 1.55 0.01 0.1774 0.0010 2.9 KB 1.25
Method_Mockolate 10 726.4 ns 1.92 ns 1.60 ns 1.00 0.00 0.1545 0.0010 2.53 KB 1.00
Method_Moq 10 183,699.6 ns 593.11 ns 525.78 ns 252.90 0.88 0.9766 0.7324 18.48 KB 7.30
Method_NSubstitute 10 8,132.7 ns 21.94 ns 20.52 ns 11.20 0.04 0.7324 0.0153 12.07 KB 4.77
Method_FakeItEasy 10 9,572.9 ns 47.95 ns 42.50 ns 13.18 0.06 0.9766 0.0305 16.05 KB 6.34
Method_Imposter 10 1,163.6 ns 14.75 ns 13.07 ns 1.60 0.02 0.3376 0.0057 5.52 KB 2.18
Method_TUnitMocks 10 1,651.3 ns 6.76 ns 6.33 ns 2.27 0.01 0.2747 0.0019 4.49 KB 1.77
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon Platinum 8370C CPU 2.80GHz (Max: 2.79GHz), 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v4

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Method N Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Property_Mockolate 1 670.4 ns 2.64 ns 2.34 ns 1.00 0.00 0.1049 - 2.58 KB 1.00
Property_Moq 1 11,155.9 ns 17.58 ns 13.73 ns 16.64 0.06 0.3662 - 10.39 KB 4.03
Property_NSubstitute 1 7,630.1 ns 21.76 ns 20.35 ns 11.38 0.05 0.4578 - 11.45 KB 4.44
Property_FakeItEasy 1 8,300.8 ns 23.17 ns 19.35 ns 12.38 0.05 0.4578 - 11.25 KB 4.36
Property_Imposter 1 571.4 ns 4.00 ns 3.12 ns 0.85 0.01 0.1268 0.0010 3.13 KB 1.21
Property_TUnitMocks 1 951.4 ns 4.74 ns 4.43 ns 1.42 0.01 0.1020 - 2.51 KB 0.97
Property_Mockolate 10 1,364.9 ns 6.30 ns 5.26 ns 1.00 0.01 0.1240 - 3.07 KB 1.00
Property_Moq 10 17,992.5 ns 47.00 ns 41.66 ns 13.18 0.06 0.7324 - 18.28 KB 5.95
Property_NSubstitute 10 16,968.0 ns 27.76 ns 21.67 ns 12.43 0.05 0.8545 - 21.08 KB 6.87
Property_FakeItEasy 10 19,611.0 ns 37.33 ns 34.92 ns 14.37 0.06 1.2512 0.0305 30.8 KB 10.03
Property_Imposter 10 1,451.4 ns 8.39 ns 7.85 ns 1.06 0.01 0.1888 0.0019 4.67 KB 1.52
Property_TUnitMocks 10 2,866.8 ns 9.91 ns 9.27 ns 2.10 0.01 0.1869 - 4.66 KB 1.52
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.203
[Host] : .NET 10.0.7 (10.0.7, 10.0.726.21808), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Method Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Callback_Mockolate 388.6 ns 2.13 ns 1.99 ns 1.00 0.01 0.1197 - 1.96 KB 1.00
Callback_Moq 95,237.4 ns 341.28 ns 302.53 ns 245.10 1.43 0.4883 0.2441 8.88 KB 4.53
Callback_NSubstitute 4,112.3 ns 7.45 ns 6.61 ns 10.58 0.05 0.4730 0.0076 7.74 KB 3.95
Callback_FakeItEasy 4,526.6 ns 12.36 ns 10.32 ns 11.65 0.06 0.4120 0.0153 6.81 KB 3.47
Callback_Imposter 397.6 ns 0.90 ns 0.76 ns 1.02 0.01 0.1454 0.0010 2.38 KB 1.22
Callback_TUnitMocks 650.5 ns 7.88 ns 7.37 ns 1.67 0.02 0.1602 0.0010 2.63 KB 1.34

@github-actions
Copy link
Copy Markdown

This is addressed in release v3.0.0.

@github-actions github-actions Bot added the state: released The issue is released label Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working state: released The issue is released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant