Ответ 1
Это связано с предполагаемым [StructLayout], прикрепленным к структуре, поле Пакет является важным. Он диктует, как члены структуры выровнены после того, как их маршалируются. Значение по умолчанию для Pack равно 8. В нем указано, что любой член размером менее или равным 8 байтам выравнивается. Другими словами, короткий будет выровнен по отношению к смещению, которое кратно 2, int до 4, длинному или двойному до 8.
Ключевым моментом является то, что выравнивание должно работать, когда создается массив структур. Проще продемонстрировать более простой пример:
using System;
using System.Runtime.InteropServices;
class Program {
static void Main(string[] args) {
Console.WriteLine(Marshal.SizeOf(typeof(Example)));
Console.ReadLine();
}
}
struct Example {
public int a;
public short b;
}
Выход: 8
Элемент a
заставляет увеличивать размер, добавляются два дополнительных байта заполнения, чтобы гарантировать, что int по-прежнему выравнивается со смещением, которое кратно 4, когда структура используется в массиве. Вы можете изменить результат, применив атрибут:
[StructLayout(LayoutKind.Sequential, Pack = 2)]
struct Example {
public int a;
public short b;
}
Выход: 6
Элемент a
теперь будет неправильно выровнен, когда структура будет использоваться в массиве.
Назад к руководству, вы не можете видеть его из декларации, но он состоит из нескольких членов. Первый - это приватное поле с именем _a
, и это int. Поэтому для указания Guid требуется выравнивание по 4 байт. Таким образом, необходимы 2 дополнительных байта заполнения, чтобы ваша структура правильно выравнивалась, когда она используется в массиве. Вам понадобится пакет Pack = 1 или Pack = 2 на S2, чтобы получить 18 байт.
Подробнее о структурах и о том, как они обрабатываются в .NET в этом ответе.