C# 内联委托的缓冲区大小不同

C# 内联委托的缓冲区大小不同,c#,.net,oop,C#,.net,Oop,我在使用内联函数时遇到了这个场景。这在我脑海中提出了几个问题。 示例1:(全局测试数据) 示例1:size=1308 示例2:size=127 我无法找出两种情况下缓冲区大小不同的原因。(我的重点): 序列化是将对象转换为字节流以存储该对象或将其传输到内存、数据库或文件的过程其主要目的是保存对象的状态,以便在需要时重新创建对象 成员方法显然不是对象的状态。它属于对象的类型。这个类的每个对象都有相同的方法,所以序列化它没有意义。因此,对于第二个示例,序列化程序仅缓冲元数据以区分序列化对象的类型,因

我在使用内联函数时遇到了这个场景。这在我脑海中提出了几个问题。
示例1:(全局测试数据)

示例1:size=1308
示例2:size=127
我无法找出两种情况下缓冲区大小不同的原因。

(我的重点):

序列化是将对象转换为字节流以存储该对象或将其传输到内存、数据库或文件的过程其主要目的是保存对象的状态,以便在需要时重新创建对象

成员方法显然不是对象的状态。它属于对象的类型。这个类的每个对象都有相同的方法,所以序列化它没有意义。因此,对于第二个示例,序列化程序仅缓冲元数据以区分序列化对象的类型,因为这就是全部内容

但是,在第一个示例中,您有一个动态分配的委托成员。它是一个成员字段,可以在类中轻松操作。没有什么能阻止你编写像这样的代码

class MyClass
{
    Func<int, int> testDeligate = (a) => { a = +10; a = +20; return a; };
    public void MutateMe()
    {
        testDelegate = (a) => 10 * a;
    }
}
class-MyClass
{
Func testDeligate=(a)=>{a=+10;a=+20;返回a;};
公共无效变位()
{
testDelegate=(a)=>10*a;
}
}
在这种情况下,委托成员的值是对象状态的一部分。因此,序列化程序需要对进入分配的lambda实现的所有数据进行编码

请注意,如果将字段更改为
static
,则会得到与示例2相同的大小。同样,因为字段不再是对象状态的一部分,而是类型的一部分


您可能想知道如果将字段更改为
只读
,会发生什么情况-答案是没有,它仍然需要序列化(与示例1的效果相同),因为它仍然可以在运行时动态计算,例如在ctor中,因此,它仍然是对象状态的一部分。

没有任何成员的序列化类的缓冲区将始终小于具有成员的序列化类的缓冲区二进制序列化通过序列化类的字段来工作。示例2没有字段。示例1变得强大不仅因为testDeligate字段,还因为它必须序列化C#编译器生成的不可见类来实现lambda表达式。请注意这是多么脆弱,序列化的数据很容易在代码中的更改中变得无效。@HansPassant因此最好使用在方法中定义的内联函数?
[Serializable]
class TestClass
{
    public void testMethod()
    {
        Func<int, int> testDeligate = (a) => { a = +10; a = +20; return a; };
        int xx = 10;
        if (xx == 1)
        {
            testDeligate(10);
            return;
        }
        else if (xx == 2)
        {
            testDeligate(20);
            return;
        }
        else if (xx == 3)
        {
            testDeligate(33);
            return;
        }
        return;
    }
}  
    TestClass testClass = new TestClass();
    var bf = new BinaryFormatter();
    var ms = new MemoryStream();
    bf.Serialize(ms, testClass);
    var size = ms.Length;  
class MyClass
{
    Func<int, int> testDeligate = (a) => { a = +10; a = +20; return a; };
    public void MutateMe()
    {
        testDelegate = (a) => 10 * a;
    }
}