Изменяет ли размер структуры нарушение в С#?

Просто любопытно, меняет ли размер типа struct/value разрывное изменение в С#? Структуры, как правило, более чувствительны в плане памяти, так как их изменение напрямую влияет на размер массивов/других структур. Существуют ли какие-либо примеры кода, который разбивается, как двоично-мудрый, так и исходный, после изменения структуры структуры в используемой библиотеке?

ПРИМЕЧАНИЕ. Под "breaks" я подразумеваю, что он вообще не компилируется, или IL недействителен. Так, например, я бы не стал рассматривать это нарушение:

// My.Library v1
public struct MyStruct {}

// My.Library v2
public struct MyStruct { int _field; }

// App code
using My.Library;
using System.Runtime.InteropServices;

Console.WriteLine(Marshal.SizeOf<MyStruct>()); // before printed 1, now prints 4

поскольку он все еще работает.

Ответ 1

Изменение размера путем добавления полей в порядке для строго управляемого кода.

Добавление полей (ов) не является изменением, поскольку код будет перезаписываться с новым типом, и все распределения будут использовать правильный размер. Так как это тип значения, новые поля будут правильно инициализированы пустым значением.

Удаление/изменение типов существующих полей или свойств определенно нарушает изменения.

Типы значений запечатаны, поэтому другие типы библиотек не могут быть получены из этого типа - поэтому в отличие от классов они не могут создавать проблемы с "этот производный класс не реализовал новый метод виртуального свойства/интерфейса".

Примечание: если тип значения используется для взаимодействия или любого другого типа двоичной сериализации вне вашего контроля, чем любое нарушение прерывается.

т.е. кто-то использовал MyLib.Point {int x;int y;} для сохранения списка точек с двоичной сериализацией в файл. Если теперь "MyLib" добавляет новое поле в MyLib.Point, чем сериализованные данные больше не могут быть прочитаны с помощью двоичной сериализации. Аналогичная проблема с встроенным взаимодействием.

Ответ 2

Да, несовместимость исходного кода, безусловно, возможна даже в строго управляемом коде, если вы добавите новое поле. Взяв ваш пример, он компилируется с версией 1, но не с версией 2:

MyStruct s;
Console.WriteLine(s);

Причина в том, что С# позволяет использовать struct local, если всем полям присвоены значения. В версии 1 нет полей, поэтому s "определенно назначается". Однако, если поле добавлено в версии 2, даже если оно является приватным, то это больше не компилируется, потому что s больше не определенно назначается.

Этот случай должен быть двоичным, поскольку CLR гарантирует инициализацию полей их значениями по умолчанию.

У Джареда Парсонса был хороший пост в блоге по теме частных полей в структурах, где он описывает другие случаи, когда изменение частных деталей реализации было бы опасным (для небезопасного кода) или взлома.