2016-09-29 196 views
1

我从一个IntPtr开始从发送周期性数据包的硬件来源的结构化数据。线程从Intptr缓冲区复制一个数据包,并将byte []放入队列中。稍后读取队列并使用this answer将byte []转换为结构,并成为Packet类型的集合(数组)。c#如何将结构数组转换为数组结构

struct Packet { 
    long time; 
    int field1; 
    short field2; 
} 

Packet[] array_of_packet; 

没有复制结构定义,我想使用数据,好像它是阵列的结构。

这种格式允许其他功能使用它们作为载体:

Plot(data.time, data.field1); 
+0

我输了!无论如何,它应该是很长的时间,而不是很长的时间[] – Nair

+0

那么,这是一个完全不同的布局。您需要手动逐项复制所有内容。 – Luaan

+0

你真的应该看看创建[不可变结构](http://stackoverflow.com/questions/3751911/why-are-c-sharp-structs-immutable)。 – juharr

回答

3

如果你想要的是一个简单的方法来转换成数组,然后只使用LINQ:

Plot (array_of_packet.Select(p => p.time).ToArray(), 
     array_of_packet.Select(p => p.field1).ToArray()); 

如果你正在寻找一种神奇的方式来重新排列内存中的数据,而不需要复制的代价,那么你的运气不好。 ;-)

0

很容易使用LINQ

data.time = array_of_packet.Select(p => p.time).ToArray(); 
data.field1 = array_of_packet.Select(p => p.field1).ToArray(); 
data.field2 = array_of_packet.Select(p => p.field2).ToArray(); 

虽然你需要做的属性public

更effecient解决方案可能是

var time = new long[array_of_packet.Length]; 
var field1 = new int[array_of_packet.Length]; 
var field2 = new short[array_of_packet.Length]; 
for(int i = 0; i < array_of_packet.Length; i++) 
{ 
    time[i] = array_of_paket[i].time; 
    field1[i] = array_of_paket[i].field1; 
    field2[i] = array_of_paket[i].field2; 
} 

data.time = time; 
data.field1 = field1; 
data.field2 = field2; 
0

您可以创建一个包装类提供了一个类似数组的访问器语法:

class ArrayWrapper<T, TField> 
{ 
    Func<T, TField> getField; 
    T[] array; 

    public ArrayWrapper(T[] array, Func<T, TField> getField) 
    { 
     this.array = array; 
     this.getField = getField; 
    } 

    public TField this[int index] 
    { 
     get { return this.getField(this.array[index]);} 
    } 

} 

然后,用一个简单的helper方法是这样的:

ArrayWrapper<T, TField> Wrap<T, TField>(T[] array, Func<T, TField> getField) 
{ 
    return new ArrayWrapper<T, TField>(array, getField); 
} 

您可以创建这样一个对象:

var data = new 
{ 
    time = Wrap(array_of_packet, p => p.time), 
    field1 = Wrap(array_of_packet, p => p.field1), 
    field2 = Wrap(array_of_packet, p => p.field2) 
}; 

...它可用于你想要的方式:

Plot(data.time, data.field1); 

根据您的具体需求,您可以通过多种方式详细说明:

  • 使类实现一个像IList<TField>这样的接口,以便Plot()可以以不知底层类型的方式编写。 (阵列已经实现了IList<TField>。)
  • 如果性能是高优先级,而不是使用一个委托(Func<,>),你可以添加where T is structArrayWrapper定义,并有ArrayWrapper采取字节作为其构造函数的参数偏移,并做一些unsafe魔法可以更快地访问该字段的数据。
+1

当我问这个问题 - 这就是我正在寻找的 - – pathfinder

+0

@brainfog:我认为这可能是。我喜欢LINQ,但它听起来像你试图避免将数据复制到多个数组中。 – StriplingWarrior

+0

最初我一直在想它:1)收集数据2)转换为结构和它们的数组3)转换为数组结构而不用重新输入原始结构(因为我有很多他们之后可能会改变) – pathfinder