What is the difference between structures containi

2019-05-28 10:37发布

问题:

Ok, I'm now very confused. After my last question had several people comment about changing bool to uint I verified they are the same size by:

    Console.WriteLine("sizeof bool = {0}", Marshal.SizeOf(typeof(bool)));
    Console.WriteLine("sizeof uint = {0}", Marshal.SizeOf(typeof(uint)));

Which of course prints:

sizeof bool = 4
sizeof uint = 4

That said, I then broke down and gave their suggestions a try anyway... Changing a single bool inside a structure to a uint. What I can't figure out for the life of me is why this made it work...

So this works:

[StructLayout(LayoutKind.Sequential)]
public struct KEY_EVENT_RECORD
{
    public bool bKeyDown;
    public short wRepeatCount;
    public short wVirtualKeyCode;
    public short wVirtualScanCode;
    public char UnicodeChar;
    public int dwControlKeyState;
}

When used in this structure:

[StructLayout(LayoutKind.Explicit)]
public struct INPUT_RECORD
{
    [FieldOffset(0)] public short EventType;
    [FieldOffset(4)] public KEY_EVENT_RECORD KeyEvent;
}

But in this structure it breaks:

[StructLayout(LayoutKind.Explicit)]
public struct INPUT_RECORD
{
    [FieldOffset(0)] public short EventType;
    [FieldOffset(4)] public KEY_EVENT_RECORD KeyEvent;
    [FieldOffset(4)] public MOUSE_EVENT_RECORD MouseEvent;
    [FieldOffset(4)] public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
    [FieldOffset(4)] public MENU_EVENT_RECORD MenuEvent;
    [FieldOffset(4)] public FOCUS_EVENT_RECORD FocusEvent;
}

Yet when I change bool bKeyDown to uint in the KEY_EVENT_RECORD structure it starts working again...

Can someone please explain this behavior?

I really would like to know the why of it so that I can avoid this undocumented feature (aka bug) in the future.

回答1:

Try setting the field type to bool and add the attribute [MarshalAs(UnmanagedType.Bool)].

[StructLayout(LayoutKind.Sequential)]
public struct KEY_EVENT_RECORD
{
    [MarshalAs(UnmanagedType.Bool)]
    public bool bKeyDown;
    public short wRepeatCount;
    public short wVirtualKeyCode;
    public short wVirtualScanCode;
    public char UnicodeChar;
    public int dwControlKeyState;
}

Docs for MarshalAsAttribute Docs for UnmanagedType



回答2:

bools are 1byte --> sizeof (C# Reference)

Also, see Default Marshaling for Boolean Types



回答3:

Question reworded with a new sample:

Boolean Marshalling with LayoutKind.Explicit, Is this broken or failing as designed?