rongfengliang / protobuf-net

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

float[] does not seem to work #274

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Please include an e-mail address if this might need a dialogue!
==============

What steps will reproduce the problem?

1. Try to serialize/deserialize a float[] array

2. Do it either as a simple declaration or (as I want to be able to do) using 
TypeModel

What is the expected output? What do you see instead?

I expect to see that the array that is passed into my class's set accessor by 
ProtoBuf would be the same as I returned from the get accessor when I 
serialized it.

What I get depends on the way in which I use protobuf. If I use the simplest 
method of everything declared at compile time, then I get two copies of data 
deserialized, e.g. {1, 2, 3, 1, 2, 3} when the original was only {1, 2, 3}.

If I use the TypeMethod system to build the definition dynamically, then I also 
get an array that is twice as long as I expect, but the first part is all 
zeroes, e.g. {0, 0, 0, 1, 2, 3}

What version of the product are you using? On what operating system?

This is r480 on Win7 x86

Please provide any additional information below.

I attach a ZIP of a simple VS2010 project that shows the problem. Put a 
breakpoint in the set accessor for FloatArray and examine the "value" that 
protobuf passes to it. For me, it is not the same as is being returned from the 
get accessor.

This is only the simple case, though. I didn't bother with generating a 
TypeModel example of the as I am assuming that they have the same cause.

Dan

Original issue reported on code.google.com by danny.p...@gmail.com on 26 Feb 2012 at 9:18

Attachments:

GoogleCodeExporter commented 9 years ago
I'm on mobile and haven't had chance to look at the example yet, but I'm 
**guessing** the default array values are set in a constructor; in which case 
this is not unexpected: options;

- use SkipConstructor to bypass the default initialization
- use a before-deserialization callback for the same

I will investigate to confirm, though

Original comment by marc.gravell on 26 Feb 2012 at 10:51

GoogleCodeExporter commented 9 years ago
I am returning the array directly from the get accessor, I didn't even bother 
creating an explicit ctor.

namespace protobuf_array
{
   [ProtoContract]
   public class FloatArray
   {
      [ProtoMember(1)]
      public float[] floatArray
      {
         get
         {
            return new float[] { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f };
         }
         set
         {
            float[] t = value;
         }
      }
   }
}

Dan

Original comment by danny.p...@gmail.com on 27 Feb 2012 at 12:15

GoogleCodeExporter commented 9 years ago
Right; indeed. Protobuf is designed (by Google, not me) as an 
appendable/mergeable format, which means that new list items are **appended**. 
If your "get" always returns data, then deserialization is essentially "get [6 
items]; append [now 12 items]; set [12 items]". There are ways of tweaking this 
- for example, you can use `OverwriteList = true` in the `[ProtoMember(...)]` 
to tell it to replace rather than append. However, fundamentally this is *not* 
how array properties are usually implemented, and the unusual scenario is 
causing unusual results. A more common scenario would be simple:

    [ProtoMember(1)]
    public float[] FloatArray {get;set;}

or, for a list:

    private readonly List<float> list = new List<float>();
    [ProtoMember(1)]
    public List<float> FloatList { get { return list; } }

both of which would work fine. If the *constructor* (or field-initializer) 
places default items in the list/array, then there are mechanisms (as mentioned 
previously) of avoiding that too.

Original comment by marc.gravell on 27 Feb 2012 at 6:58

GoogleCodeExporter commented 9 years ago
That makes perfect sense, now. I wasn't anticipating the "append" behaviour 
(Protocol Buffers is just a black-box to me).

I agree that it's not how arrays are usually implemented, but I wanted to 
force-feed this application with some predictable data at the front end, so 
that I could more easily understand what was coming out of the back of it.

Thank you for your time and help!

Dan

Original comment by danny.p...@gmail.com on 27 Feb 2012 at 10:25