-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Version Used:
Microsoft Visual Studio Professional 2022
Version 17.3.0 Preview 3.0
VisualStudio.17.Preview/17.3.0-pre.3.0+32708.82
Microsoft .NET Framework
Version 4.8.04084
Steps to Reproduce:
Compile and run the following code:
using System;
var x = 42;
scoped var r = new R();
r.field = ref x;
ref struct R
{
public ref int field;
public R()
{
Console.WriteLine("explicit ctor");
}
}Expected Behavior:
The code runs without exceptions.
Actual Behavior:
The code crashes with a NullReferenceException in public R() constructor
Notes:
The compile emits the following IL for public R():
.method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8
// [12 3 - 12 4]
IL_0000: nop
IL_0001: ldarg.0 // this
IL_0002: ldfld int32& R::'field'
IL_0007: ldc.i4.0
IL_0008: stind.i4
// [13 5 - 13 40]
IL_0009: ldstr "explicit ctor"
IL_000e: call void [System.Console]System.Console::WriteLine(string)
IL_0013: nop
// [14 3 - 14 4]
IL_0014: ret
} // end of method R::.ctor
Which tries to store 0 value in the unassigned ref int field field resulting in a NullReferenceException
It seems that Roslyn should treat ref fields as references and leave null values if such fields aren't assigned in a constructor.
Interestingly, if you remove the constructor completely and use default struct constructor the code runs correctly, i.e. code gen that "zeroes" struct memory runs differently in default struct constructor and any explicit one that doesn't initialize a byref field.
Note that the current behavior limits usability of other features related to low level structs, e.g. you can assign ref fields via object initializers but the current behavior forces you to assign a reference in the struct constructor first only to be immediately overridden via an object initializer
Metadata
Metadata
Assignees
Labels
Type
Projects
Status