我知道我可以通过IList枚举如下:
public byte[] ConvertToByteArray(IList<ArraySegment<byte>> list) {
IList<byte> newList = new List<byte>();
foreach(var asb in list) {
for ( int i = asb.Offset; i < (asb.Offset + asb .Count); i++ ) {
newList.Add(asb.Array[i]);
}
}
return newList.ToArray();
}
但这看起来相当丑陋,有没有更好的方法呢?
答案 0 :(得分:7)
这可能是一个潜在的棘手问题,因为ArraySegment
实际上只是一个原始数组的视图包装器,并且对于在数组周围创建的ArraySegment
的数量没有限制(存储作为参考,而不是ArraySegment.Array
属性中的副本 - 所以你不能通过一次性提取数组来做任何技巧。
话虽这么说,你的初始代码可以略微提高。缓冲副本。这假设您希望在基础数组中指向相同值的段中的值在结果数组中重复。
public byte[] ConvertToByteArray(IList<ArraySegment<byte>> list)
{
var bytes = new byte[list.Sum (asb => asb.Count)];
int pos = 0;
foreach (var asb in list) {
Buffer.BlockCopy (asb.Array, asb.Offset, bytes, pos, asb.Count);
pos += asb.Count;
}
return bytes;
}
它会迭代list
两次(以获得总计数,但对于较大的ArraySegments,在我的综合测试中,缓冲复制比额外迭代更大的胜利是一个损失)。与往常一样,衡量它是否是一个性能关键的代码路径。
答案 1 :(得分:0)
一旦遇到同样的问题,我就发现了对你的问题的非常好的解释。 (http://www.fotia.co.uk/fotia/DN.01.CoVariantGenericList.aspx)
我已经实现了您可能希望使用的代码类型,方法是创建一个继承自泛型列表类的类,并添加一个为我做迭代的构造函数。
public class bytes : List<byte>
{
public bytes()
{
}
public bytes (IList<ArraySegment<byte>> list)
{
for ( int i = 0; i < list.Count; i++ )
{
this.Add(asb.Array[i]);
}
}
}
然后,在您的代码中,您可以拥有:
bytes myList = new bytes(yourIList);
这不会消除对转换的需要,但它会隐藏代码。