3 ms·
> The interior layout of the union struct is chosen to allow for efficient storage of the data found within the different possible member types with tradeoffs b
by zamalek 2y ago
> The interior layout of the union struct is chosen to allow for efficient storage of the data found within the different possible member types with tradeoffs between speed and size chosen by the compiler.
Having _attempted_ (and being bitten by) far too much black magic with C# unions in the past (using FieldOffset), there is an unfortunate situation here: aliasing a pointer/ref value and value is UB. This means that a struct union of a u64 and an object would need separate fields for each, wasting 8 bytes. That is, unless the ryujit/gc is updated with knowledge about this.
- jasomill 2y agoNot UB, illegal. Per ECMA 335, II.10.7: It is possible to overlap fields in this way, though offsets occupied by an object reference shall not overlap with offsets occupied by a built-in value type or a part of another object reference. Per .NET 8.0: using System.Runtime.InteropServices; var s = new S { Bar = "Baz" }; [StructLayout(LayoutKind.Explicit)] public struct S { [FieldOffset(0)] public UInt64 Foo; [FieldOffset(0)] public Object Bar; } compiles, but throws System.TypeLoadException: Could not load type 'S' from assembly 'foo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field. Interestingly, this code elicits a warning ILC: Method '[foo]Program.<Main>$(string[])' will always throw because: Failed to load type 'S' from assembly 'foo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because of field offset '0' from the AOT compiler, but none from the C# compiler.
- jaredpar 2y ago> from the AOT compiler, but none from the C# compiler. The C# compiler has very little knowledge of `[FieldOffset]`. It's expected that developers understand the runtime implications of this.