是否需要将IList <ArraySegment <byte >>转换为byte []而不通过List枚举并添加到新的byte []?

jas*_*ota 1 c# bytearray

我理解我可以通过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();
}
Run Code Online (Sandbox Code Playgroud)

但这看起来相当难看,有没有更好的方法呢?

Mat*_*ght 7

这可能是一个潜在的棘手问题,因为ArraySegment它实际上只是一个原始数组的视图包装器,并且对于ArraySegment在数组周围创建的s 数量没有限制(在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;
}
Run Code Online (Sandbox Code Playgroud)

这会迭代list两次(以获得总计数,但对于较大的ArraySegments,在我的综合测试中,缓冲复制比额外迭代更大的胜利是一个损失).与往常一样,衡量它是否是一个性能关键的代码路径.

  • 我认为有一个错误.你在做Buffer.BlockCopy之前递增pos(pos + = asb.Count将作为参数传递给Bufer.BlockCopy求和值,所以在第一个循环中,pos是list [0] .count而不是0. pos + = asb.Count到下一行并添加一些括号. (2认同)