序列化同一个对象会产生不同的流吗?

Bra*_*vic 5 .net serialization

是否有任何情况下序列化相同的对象可能会产生不同的流(假设其中一个格式化内置的.NET用于两个序列化)?

这在下面的讨论中提出了这个职位.有人声称这可能发生,但没有提供具体的解释,所以我想知道是否有人可以解释这个问题?

Ali*_*tad 6

正如我在SO问题的评论中所解释的那样,通过优化字符串输出引起问题(至少我发现的情况).看起来如果字符串是相同的引用,那么它将输出一次.

那么我们的示例代码是如何使用长字符串来表示对象的属性并更改一个字符串的引用然后序列化.然后将流再次反序列化为对象(这次是因为字符串被实现,使用相同的引用)然后再次序列化.这次流更小.

好的,这是证明代码:

[Serializable]
public class Proof
{
    public string S1 { get; set; }
    public string S2 { get; set; }
    public string S3 { get; set; }
}

class Program
{
    static void Main(string[] args)
    {

        const string LongString =
            "A value that is going to change the world nad iasjdsioajdsadj sai sioadj sioadj siopajsa iopsja iosadio jsadiojasd ";

        var proof = new Proof() {
            S1 = LongString,
            S2 = LongString,
            S3 = LongString
        };

        proof.S2 = LongString.Substring(0, 10) + LongString.Substring(10); // just add up first 10 character with the rest. 
               //This just makes sure reference is not the same although values will be

        Console.WriteLine(proof.S1 == proof.S2);
        Console.WriteLine(proof.S1 == proof.S3);
        Console.WriteLine(proof.S2 == proof.S3);
        Console.WriteLine("So the values are all the same...");

        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        bf.Serialize(stream, proof);
        byte[] buffer = stream.ToArray();
        Console.WriteLine("buffer length is " + buffer.Length); // outputs 449 on my machine
        stream.Position = 0;
        var deserProof = (Proof) bf.Deserialize(new MemoryStream(buffer));
        deserProof.S1 = deserProof.S2;
        deserProof.S3 = deserProof.S2;
        MemoryStream stream2 = new MemoryStream();
        new BinaryFormatter().Serialize(stream2, deserProof);

        Console.WriteLine("buffer length now is " + stream2.ToArray().Length); // outputs 333 on my machine!!
        Console.WriteLine("What? I cannot believe my eyes! Someone help me ........");

        Console.Read();
    }
Run Code Online (Sandbox Code Playgroud)