После MSDN (выделено мое):
Сериализация - это процесс преобразования объекта в поток байтов для хранения объекта или передачи его в память, базу данных или файл. Его основная цель - сохранить состояние объекта , чтобы иметь возможность воссоздать его при необходимости.
Метод-член, очевидно, не является состоянием объекта. Это относится к типу объекта. У каждого объекта этого класса будет один и тот же метод, поэтому нет смысла его сериализовывать. Так что для вашего второго примера сериализатор буферизует только метаданные, чтобы различать тип сериализованного объекта, поскольку это все, что есть.
В вашем первом примере, однако, у вас есть динамически назначенный член делегата. Это поле члена, которым можно легко манипулировать в классе. Ничто не мешает вам писать код вроде
class MyClass
{
Func<int, int> testDeligate = (a) => { a = +10; a = +20; return a; };
public void MutateMe()
{
testDelegate = (a) => 10 * a;
}
}
В этом случае значение члена делегата составляет часть состояния вашего объекта. Таким образом, сериализатору необходимо кодировать все данные, которые поступают в реализацию назначенной лямбды.
Обратите внимание, что если вы измените поле на static
, вы снова получите тот же размер, что и, например, 2., так как поле больше не будет частью состояния объекта, а будет static
часть типа.
Вы можете задаться вопросом, что произойдет, если вы измените поле на readonly
- ответ - ничто, его все равно нужно будет сериализовать (такой же эффект, как в примере 1.), поскольку он все еще может быть динамически вычислен в время выполнения, например в ctor, так что он все еще будет частью состояния объекта.