开发者

How to convert a bunch of primitive value types to byte array efficiently in .NET in Silverlight compatible manner?

开发者 https://www.devze.com 2023-02-03 11:48 出处:网络
Observe the following .NET type: public class X { public DateTime Timestamp {get;set;} public double Value {get;set;}

Observe the following .NET type:

public class X
{
  public DateTime Timestamp {get;set;}
  public double Value {get;set;}
  public double Min {get;set开发者_StackOverflow中文版;}
  public double Max {get;set;}
}

I need to convert an array of N elements of X to a single byte array and vice versa efficiently and the code must be Silverlight compatible (meaning forget about the binary serialization, be it efficient or not).

My solution is:

public void GetState(SerializationInfo info)
{
  var stream = new MemoryStream();
  var buf = BitConverter.GetBytes(Count);
  stream.Write(buf, 0, buf.Length);
  foreach (var item in this)
  {
    buf = BitConverter.GetBytes(item.Timestamp.Ticks);
    stream.Write(buf, 0, buf.Length);
    buf = BitConverter.GetBytes(item.Value);
    stream.Write(buf, 0, buf.Length);
    buf = BitConverter.GetBytes(item.Min);
    stream.Write(buf, 0, buf.Length);
    buf = BitConverter.GetBytes(item.Max);
    stream.Write(buf, 0, buf.Length);
  }
  info.AddValue("Data", stream.ToArray());
}
public void SetState(SerializationInfo info)
{
  var data = info.GetValue<byte[]>("Data");
  int count = BitConverter.ToInt32(data, 0);
  Capacity = count;
  int offset = sizeof(int);
  while (count-- > 0)
  {
    Add(new ExtendedNormalizedSample(
      new DateTime(BitConverter.ToInt64(data, offset)),
      BitConverter.ToDouble(data, offset += sizeof(long)),
      BitConverter.ToDouble(data, offset += sizeof(double)),
      BitConverter.ToDouble(data, offset += sizeof(double))));
    offset += sizeof(double);
  }
}

(Ignore the SerializationInfo stuff - irrelevant for the question)

Anyway, what I do not like about my solution is the abundance of byte[] arrays created during the serialization. I mean, every call to BitConverter.GetBytes returns a new byte array and although, creating new byte arrays is cheap in .NET, but still, as a former C++ developer, this seems to be an awful waste to use a new byte array each time, whereas a single byte array can be reused.

Can anyone suggest a better solution (remember, it must be Silverlight compatible, so do not propose unsafe code).

Thanks.


The DateTime Ticks could be encoded as an integer via shift operations etc. The float - you might try using a union to swap for int, and then encode the int with shift operations:

[StructLayout(LayoutKind.Explicit)]
struct MyUnion
{
    [FieldOffset(0)]
    private int i;
    [FieldOffset(0)]
    private float f;

    public static int ToInt32(float value) {
        MyUnion u = new MyUnion();
        u.f = value;
        return u.i;
    }
    public static float ToSingle(int value) {
        MyUnion u = new MyUnion();
        u.i = value;
        return u.f;
    }
}

Then if you have an existing Stream or byte[] you can encode (depending on your chosen endianness) something like:

int iValue = MyUnion.ToInt32(fValue);


int offset = ...;
...
buffer[offset++] = (byte)iValue;
buffer[offset++] = (byte)(iValue >> 8);
buffer[offset++] = (byte)(iValue >> 16);
buffer[offset++] = (byte)(iValue >> 24);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号