将部分数组添加到List的内存有效方法

时间:2013-07-16 16:03:11

标签: c# arrays list c#-2.0

假设我有以下变量:

byte[] fileData;
List<byte> bundleData;

我希望将fileData的连续部分添加到bundleData。我目前的方法基本上如下:

int startIndex = 20, endIndex = 80;
byte[] transferredData = new byte[endIndex - startIndex];
Array.Copy(fileData, startIndex, transferredData, 0, transferredData.Length);
bundleData.AddRange(transferredData);

创建中间数组工作正常,但它使用看似不必要的副本。有没有办法直接添加数据,而不使用冗余阵列?

作为参考,我在这个项目上使用.NET 2.0。

4 个答案:

答案 0 :(得分:2)

列表&lt; T&gt; class本质上只是包装一个T数组,当数组已满时,该数组被更大的T数组替换。将字节数组追加到List&lt; byte&gt;的最快方法将字节直接复制到内部字节数组中。

然而,列表&lt; T&gt; class不公开内部数组,所以最好的选择可能是确保列表有足够的容量,不需要多次替换内部数组,然后逐个添加每个字节:

bundleData.Capacity += endIndex - startIndex + 1;

for (int i = startIndex; i <= endIndex; i++)
{
    bundleData.Add(fileData[i]);
}

您还可以尝试使用AddRange并提供字节数组的视图:

static IEnumerable<T> Range<T>(this T[] array, int offset, int count)
{
    for (int i = 0; i < count; i++)
    {
        yield return array[offset + i];
    }
}

bundleData.AddRange(fileData.Range(startIndex, endIndex - startIndex + 1));

答案 1 :(得分:1)

List.AddRange方法实现如下。我将添加一些伪代码来解释。

ICollection<T> is2 = collection as ICollection<T>;
if(is2!=null)
{
   //then use Array.Copy
}
else
{
 //Loop through GetEnumerator() and calls Insert()
}

因此,自阵列实现ICollection以来,中间阵列将是最好的想法。 希望这会有所帮助。

答案 2 :(得分:1)

如果您实际上不需要List&lt; byte&gt;例如,更好的选择可能是MemoryStream class

  

MemoryStream类

     

创建其后备存储为内存的流。

示例:

MemoryStream bundleData = new MemoryStream();
bundleData.Write(fileData, startIndex, endIndex - startIndex + 1);

答案 3 :(得分:1)

另一种(可能有效的)方法是使用LINQ:

bundleData.AddRange(fileData.Skip(startIndex).Take(endIndex - startIndex));