2011-01-09 1 views
2

다음 .NET 유형 관찰 : 나는 그 반대의 경우도 마찬가지 효율적으로 단일 바이트 배열 X의 N 요소의 배열을 변환 할 필요가Silverlight 호환 방식으로 .NET에서 원시 값 형식을 바이트 배열로 효율적으로 변환하는 방법은 무엇입니까?

public class X 
{ 
    public DateTime Timestamp {get;set;} 
    public double Value {get;set;} 
    public double Min {get;set;} 
    public double Max {get;set;} 
} 

및 코드 호환 실버해야합니다 (바이너리 직렬화에 대해 잊지 의미 , 효율적이든 아니든).

내 솔루션은 다음과 같습니다

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

(SerializationInfo에 물건 무시 - 질문에 대한 무관) 내 솔루션이 과정에서 생성 바이트 [] 배열의 풍요 로움이에 대해 내가 좋아하지 않는 무엇을, 어쨌든

을 직렬화. 내 말은, BitConverter.GetBytes에 대한 모든 호출은 새로운 바이트 배열을 반환하지만 새로운 바이트 배열을 만드는 것이 .NET에서는 저렴하지만 여전히 이전 C++ 개발자로서 매번 새로운 바이트 배열을 사용하는 것은 낭비 인 것 같습니다. 단일 바이트 배열은 재사용 될 수 있습니다.

누구나 더 좋은 해결책을 제안 할 수 있습니까? (Silverlight와 호환되어야하므로 안전하지 않은 코드를 제안하지 마십시오).

감사합니다.

+0

사이드 노트 : protobuf-net과 같은 다른 시리얼 라이저를 고려할 수도 있습니다. 모든 인코딩을 수행 할 필요가 없습니다. 특히 v2가 제공 될 때 SL이 많이 도움이되므로 매우 빠르게 처리됩니다. 그리고 매우 작은 출력이 필요합니다. 플러스 : 무료. –

+0

빠른 변화가 필요하지만 항상 protobuf-net을 유의하십시오. – mark

답변

2

DateTimeTicks는 시프트 작업 등을 통해 정수로 인코딩 할 수있는 다음은 float - 당신 수도 시프트 작업으로 int을 인코딩 한 후 int에 대한 교환하기 위해 노동 조합을 사용하여 시도하고 :

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

기존 Stream 또는 byte[]이있는 경우 선택한 엔디안에 따라 다음과 같이 인코딩 할 수 있습니다.

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

하지만 나는 두 배로 부유하지 않습니다. 따라서 int보다 오히려 길어야합니다. – mark

+0

내 생각에, 그것은 중요하지 않습니다. - 교장은 그대로 있습니다. 감사. – mark

+0

@ 마크 - 참으로; 이 경우'long'을위한 subst –

관련 문제