zhejiushizhuce / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
0 stars 0 forks source link

Error when deserializing initialized arrays #152

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
--- Repro-step ---
Run Issue.ShowTheFault() below:

public class Issue
{
    public static void ShowTheFault()
    {
        //Showing the fault
        var a1 = new IntArray { Arr = new int[] { 1, 1 } };
        Print(a1.Arr); //"1;1"
        Print(Serializer.DeepClone(a1).Arr); //"2;2;1;1"

        //Pointing at the cause
        var a = new IntArray2 { Arr = new int[] { 1, 1 } };
        Print(a.Arr); //"1;1"
        Print(Serializer.DeepClone(a).Arr); //"1;1"
    }

    [DataContract]
    private class IntArray
    {
        [DataMember(Order = 1)]
        public int[] Arr = new int[] { 2, 2 };
    }

    [DataContract]
    private class IntArray2
    {
        [DataMember(Order = 1)]
        public int[] Arr = new int[] { 2, 2 };

        [OnDeserializing]
        private void OnDeserializing()
        {
            Arr = null;
        }
    }

    static void Print<T>(IEnumerable<T> items)
    {
        Console.WriteLine(String.Join(";", items));
    }
}

--- Observed output ---
1;1
2;2;1;1
1;1
1;1

--- Expected output ---
1;1
1;1
1;1
1;1

--- Versions ---
protobuf Version: 1.0.0.282
Runtime Version: v2.0.50727
.Net 4
Win 7

--- Additional comments ---
It seems like the deserialization CONCATENATES the contents from the 
constructor-initialization and the serialized contents. 

This is especially counter-intuitive since arrays are fixed-length.

Original issue reported on code.google.com by andersgs...@gmail.com on 1 Feb 2011 at 4:05

GoogleCodeExporter commented 9 years ago
This is the expected behaviour considering that the protobuf encoding spec 
treats repeated elements as "append", not "replace". However, this has also 
come up recently, so I propose to make this optional in the v2 codebase.

Other workarounds:

- add a before-deserialization callback that wipes the field
- (v2 only) elect to skip the constructor, as this also skips field initialisers

Re fixed size; in common with other serializers it is anticipated that the 
array will be reassigned during deserialization. I you want in-place handling, 
consider per-index properties that are serialized separately.

Original comment by marc.gravell on 1 Feb 2011 at 5:42

GoogleCodeExporter commented 9 years ago
Thanks for the rapid response. 

Does the spec say anything about initialization, since this is really the 
issue? One could imagine:

On non-serialized construction:
Arr = new int[10];

On serialized construction the functional equivalent of:
Arr = AllProtbufElementConcatenated("Arr")

Any ideas on when v2 is production-ready? 

Original comment by andersgs...@gmail.com on 2 Feb 2011 at 7:46

GoogleCodeExporter commented 9 years ago
The spec I'm referring to only handles the core protobuf encoding, which 
doesn't refer to specific collection types, but the assumption is that arrays 
are treated as "repeated" elements, which are indeed appended.

Re v2 - .... I just need to grab the time to finish it. Since this all comes 
out of my non-work time it is harder to ring-fence. Soon, I hope.

Original comment by marc.gravell on 2 Feb 2011 at 8:08

GoogleCodeExporter commented 9 years ago
in v2, OverwriteList is an option on the ValueMember. It is not currently 
exposed on the attribute usage, but count be if desired.

Original comment by marc.gravell on 13 Jun 2011 at 12:29