可序列化的同一个对象产生不同的流?对象、不同、序列化

2023-09-04 10:08:19 作者:一别两宽,各生喜欢

有没有什么情况,当序列相同的对象可能会产生不同的数据流(假设格式化内置.NET用于两个序列化的)?

Is there any situation when serializing the same object could produce different streams (assuming one of the formatters built-in .NET is used for both serializations)?

这想出了下面this帖子。索赔有人提出,这可能发生,目前还没有具体的解释被提供了,所以我想知道如果任何人都可以阐明这个问题一些轻?

This came up in the discussion below this post. The claim was made that this can happen, yet no concrete explanation was offered, so I was wondering if anyone can shed some light on the issue?

推荐答案

正如我在这太问题的注释说明,这个问题是由于(至少我已经发现的情况下)的字符串输出的优化。 看来,如果字符串是相同的,则输出一次。

As I explained in the comment of that SO question, the issue is caused (at least the case I have discovered) by optimisation of the string output. It seems if strings are the same reference, then it will output it once.

因此​​,我们的样本code它使用什么样的长字符串对象的属性和改变一个字符串的引用,然后连载。然后deserialise流再次回到对象(和这个时间,因为该字符串被扣留,相同的参考时),然后再次连载。这一次的流的越小

So what we the sample code does it to use a long string for properties of an object and change the reference of one string and then serialise. Then deserialise the stream back again to object (and this time since the string is interned, same reference is used) and then serialise again. This time the stream is smaller.

确定,这里是证明code:

OK, here is the proof code:

[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();
    }