readonly struct and readonly struct instance members (optimization?)

Hey you beautiful people. Recently I experimented with readonly struct's and readonly struct instance members (as one does) However the compiler for this doesn't quite act like I expected it to. Consider something like this for instance:
public readonly struct TestStruct
{
public static TestStruct New()
=> new() { _array = new float[SomeEnumLenght] };
private readonly float[] _array;
public readonly float this[SomeEnum key] // IMO adding "readonly" to instance members when the hole struct is readonly is a bit silly, but just adding it here incase that makes a difference?
{
get => _array[(int)key];
set => _array[(int)key] = value;
}
}

static class Program
{
static void Main()
{
var test = new TestStruct();
_=test[0];
}
}
public readonly struct TestStruct
{
public static TestStruct New()
=> new() { _array = new float[SomeEnumLenght] };
private readonly float[] _array;
public readonly float this[SomeEnum key] // IMO adding "readonly" to instance members when the hole struct is readonly is a bit silly, but just adding it here incase that makes a difference?
{
get => _array[(int)key];
set => _array[(int)key] = value;
}
}

static class Program
{
static void Main()
{
var test = new TestStruct();
_=test[0];
}
}
I would expect the il for the "_=test[0];" line to be something roughly like this: ldloc.0 ldc.i4.0 call TestStruct::get_item(SomeEnum key) pop But from my testing, it seems the compiler does the less efficient route (the route of which I thought readonly struct was designed to prevent) of: ldloca.s 0 ldc.i4.0 call TestStruct::get_item(SomeEnum key) pop aka it passes a pointer of the "test" local instead of by value to the get_item call (which for my understanding passing by value would be the expected behaviour here) I'm using a custom compiler atm (I'm gonna try this with VS too) that are using the official roslyn codeanalysis nuget package
1 Reply
Tacti Tacoz
Tacti TacozOP3y ago
Apparently assigning readonly to user defined structs are mostly to defend against defensive copies (like when using the in parameter - and off course for the syntax sugar of not mutating something that shouldn't be mutated in the first place). I would have thought the way I thought it was working would be a performance benefit for structs with sizes equal or lower then 4 bytes (on 32bit systems) and 8 bytes (on 64bit systems). I feel like the roslyn guys should look into this at some point, unless I'm totally wrong about it being more efficent. I'm open to suggestions as to why you guys think they decided not to do it this way.
Want results from more Discord servers?
Add your server