Читайте спецификацию правил размещения более внимательно. Правила макета управляют макетом только тогда, когда объект отображается в неуправляемой памяти .Это означает, что компилятор может свободно размещать поля по своему усмотрению, пока объект не будет фактически экспортирован.К моему удивлению, это даже верно для FixedLayout!
Ян Рингроз прав в вопросах эффективности компилятора, и что отвечает за окончательный макет, который здесь выбран, но он имеетне имеет ничего общего с тем, почему компилятор игнорирует вашу спецификацию макета.
Несколько человек отметили, что DateTime имеет автоматическое расположение.Это основной источник вашего удивления, но причина немного неясна.В документации для автоматической разметки сказано, что «объекты, определенные с разметкой [Авто], не могут быть представлены вне управляемого кода. Попытка сделать это приводит к исключению».Также обратите внимание, что DateTime является типом значения.Включив тип значения с автоматическим макетом в вашу структуру, вы непреднамеренно пообещали, что никогда не будете подвергать структуру , содержащую , неуправляемому коду (поскольку при этом будет выставлен DateTime, и это приведет к исключению).Поскольку правила компоновки управляют только объектами в неуправляемой памяти, и ваш объект никогда не может подвергаться воздействию неуправляемой памяти, компилятор не ограничен в выборе компоновки и может делать все, что захочет.В этом случае он возвращается к политике автоматического размещения, чтобы улучшить упаковку и выравнивание структуры.
Там!Разве это не очевидно?
Все это, кстати, узнаваемо во время статической компиляции.Фактически, компилятор распознает его, чтобы решить, что он может игнорировать вашу директиву макета.Признав это, здесь должно показаться предупреждение от компилятора.На самом деле вы не сделали ничего плохого, но полезно знать, когда вы пишете что-то, что не имеет никакого эффекта.
Различные комментарии здесь, рекомендующие фиксированный макет, как правило, являются хорошим советом, но в этом случаене обязательно иметь какой-либо эффект, потому что в том числе поле DateTime освобождает компилятор от соблюдения макета вообще.Хуже того: компилятору не требуется для соблюдения макета, но бесплатно для соблюдения макета.Это означает, что последующие версии CLR могут свободно вести себя по-разному.
Лечение макета, на мой взгляд, является недостатком дизайна в CLI.Когда пользователь указывает макет, компилятор не должен заниматься им.Лучше быть проще и заставить компилятор делать то, что ему говорят.Особенно в том, что касается макета.«Умный», как мы все знаем, это четырехбуквенное слово.