Example below outputs on .NET 64bit:
but on Mono 64bit(32bit works fine) it outputs:
[StructLayout(LayoutKind.Explicit, Size = 12)]
private struct Sha1Hash
private long Data1;
private int Data3;
public static void Main(string args)
var size = sizeof(Sha1Hash);
This was uncovered by https://github.com/dotnet/roslyn/blob/f629039/src/Workspaces/Core/Portable/Workspace/Solution/Checksum.cs#L28
I can reproduce with Mono 126.96.36.199 (2017-10/a3943e28cf8)
This is caused by:
The explicit layout directive is supposed to only affect unmanaged layout, so the sizeof (T) should still return the managed size imho.
According to the ecma spec:
[Rationale: The definition of a value type can change between the time the CIL is generated and the time that it is loaded for execution. Thus, the size of the type is not always known when the CIL is generated. The sizeof instruction allows CIL code to determine the size at runtime without the need to call into the Framework class library. The computation can occur entirely at runtime or at CIL-to-native-code compilation time. sizeof returns the total size that would be occupied by each element in an array of this type – including any padding the implementation chooses to add. Specifically, array elements lie sizeof bytes apart. end rationale]
So the implementation is free to add padding, like mono does. I don't think it is a bug, more like roslyn is depending on an implementation detail.
Adding some details from a mail thread with Sam Harwell to ensure they're documented:
> The explicit layout directive is supposed to only affect unmanaged layout …
This is an incorrect statement. In ECMA-335 §II.10.7 there are two statements which make this clear:
* Fields can be accessed using pointer arithmetic and ldind to load the field indirectly or stind to store the field indirectly …
* Note: Metadata that controls instance layout is not a “hint,” it is an integral part of the VES that shall be supported by all conforming implementations of the CLI.
> So the implementation is free to add padding, like mono does.
I’m finding it hard to believe this. The most direct evidence that padding was not intended here comes from the following statement in the informative text of §II.22.8:
* If Parent indexes an ExplicitLayout type, then … PackingSize shall be 0. (It makes no sense to provide explicit offsets for each field, as well as a packing size.) [ERROR]
This interpretation is further supported by §I.9.5 (Class layout). This section explicitly provides for the CLI to modify the layout according to limitations defined in source code. The definitions of autolayout and sequentiallayout provide for the runtime to modify alignments, but no such provision is provided for explicitlayout. Rather, explicitlayout provides only for the alignment of instances of the type itself (using .size), an interpretation of the wording which is confirmed by the informative text of §II.22.8.
This landed in master with https://github.com/mono/mono/commit/6b58f1317732b9cbf6ec61921e76d7d48e362104.
It is being backported to mono:2017-12 with https://github.com/mono/mono/pull/6653