Marshal.Sizeof и BitConverter.GetBytes ведут себя по-разному на логических значениях - PullRequest
2 голосов
/ 10 октября 2019

Давайте рассмотрим этот фрагмент кода:

static void Main(string[] args)
{
    Console.WriteLine(Marshal.SizeOf(typeof(bool)));
    Console.WriteLine(String.Join(", ", BitConverter.GetBytes(true)));
}

если bool равен 1 байту, я ожидаю, что он выдаст

1
1

и если bool равен 4 байта (как целое число), я бы ожидал

4
1, 0, 0, 0 // давайте забудем о порядке байтов

Однако он выводит (в x64)

4
1

Это довольно большая проблема для меня в коде маршалинга. Кому я должен доверять?

Обратите внимание, что GetBytes принимает логическое значение в качестве ввода: enter image description here

Ответы [ 2 ]

5 голосов
/ 10 октября 2019

Оба ваших способа измерения размера bool имеют недостатки.

Marshal.SizeOf используется для определения того, сколько памяти используется, когда данный тип перенаправляется в неуправляемый код. bool назначается типу Windows BOOL, который составляет 4 байта.

BitConverter.GetBytes(bool) эффективно реализован так:

public static byte[] GetBytes(bool value) {
    byte[] r = new byte[1];
    r[0] = (value ? (byte)1 : (byte)0 );
    return r;
}

Источник .

Поэтому он всегда возвращает одноэлементный массив.

Вероятно, вы после этого получите sizeof(byte), который "возвращает количество байтов, занятых переменной данного типа". ( MSDN ). sizeof(bool) возвращает 1.

0 голосов
/ 10 октября 2019

Дело в том, что Marshal.SizeOf возвращает размер неуправляемого типа в байтах, а неуправляемый эквивалент логического типа - 4-байтовый тип Win32 BOOL. см https://stackoverflow.com/a/6420546/3478025 для подробностей

...