C# 添加字节到字节数组方法优化

C# 添加字节到字节数组方法优化,c#,C#,我有一个包含200000多个字符串的列表(每个值看起来像十六进制中的“0x01”)。我所做的是循环列表中的每个值,并将该字符串值转换为一个字节,然后将其添加到字节数组中。我遇到了一个问题-它持续时间太长(例如200000个字符串持续16秒)。我在互联网上发现了这种方法,它将一个字节添加到现有的字节数组中,但这种方法似乎非常慢: private byte[] addByteToArray(byte[] bArray, byte newByte) { byte

我有一个包含200000多个字符串的列表(每个值看起来像十六进制中的“0x01”)。我所做的是循环列表中的每个值,并将该字符串值转换为一个字节,然后将其添加到字节数组中。我遇到了一个问题-它持续时间太长(例如200000个字符串持续16秒)。我在互联网上发现了这种方法,它将一个字节添加到现有的字节数组中,但这种方法似乎非常慢:

private byte[] addByteToArray(byte[] bArray, byte newByte)
        {
            byte[] newArray = new byte[bArray.Length + 1];
            bArray.CopyTo(newArray, 1);
            newArray[0] = newByte;
            return newArray;
        }
你知道如何让这个方法在几毫秒而不是几秒钟内变得更快吗?
提前感谢您的想法

我可以想出两种可能的解决办法。添加字节速度慢的原因是每次都要创建一个新数组。您可以通过在指定索引处添加字节来创建相同大小的数组和循环,即
array[x]=List[x]

或者使用一个列表,因为它是为添加而优化的。它有一个内部容量,这是它分配的一个数组,但它通常会过度分配其大小,以允许更快地添加,而不是为每次添加调整数组大小。首先,与上述解决方案相比,它会更慢。但是,如果清除列表并重新使用它,则速度应等于数组的速度,因为列表已经分配了其内部数组,清除只会将list.length设置为0,但不会清除内部数组

您还可以使用
var list=new list(200000)指定列表的起始容量这也将抵消第一次运行时的任何速度影响。请再次注意,容量是用于后台存储的内部阵列大小。长度将返回您添加的项目数量,而不是容量

您也可以使用linq来实现这一点,这使得它非常简洁

List<byte> bytes = hexList.Select(hexString =>Convert.ToByte(hexString.Substring(2,2), 16).ToList();
List bytes=hexList.Select(hexString=>Convert.ToByte(hexString.Substring(2,2,16));
假设您的十六进制字符串列表称为hexList并带有0x前缀,这就是为什么
.Substring
方法从索引2开始,以跳过0x

我有一个包含200000多个字符串的列表(每个值看起来像十六进制中的“0x01”)。我所做的是循环列表中的每个值,并将该字符串值转换为一个字节,然后添加到字节数组中

所以你有这个:

List<String> listOfHexBytes = new List<String>() { "0x01", "0x02", "0x03", ... };
这样使用:

Byte[] asByteArray = listOfHexBytes
    .Select( Base16.ParseCStyleByte )
    .ToArray();
虽然这会导致两个数组副本,因为当输入具有已知长度时,
ToArray
不会优化(Linq有一些骨头设计问题…),但这样做也可以:

Byte[] output = new Byte[ listOfHexBytes.Count ];
for( Int32 i = 0; i < output.Length; i++ )
{
    output[i] = Base16.ParseCStyleByte( listOfHexBytes[i] );
}
Byte[]输出=新字节[listOfHexBytes.Count];
for(Int32 i=0;i
对于.Net Core,考虑到原始列表中的
src
,这应该是合理的:

var b = src.Select(s => Byte.Parse(s.AsSpan().Slice(2), System.Globalization.NumberStyles.HexNumber)).Reverse().ToArray();

注意:因为您知道每个字符串都以
0x
开头,所以跳过比使用
Convert.ToByte(s,16)稍微快一点

该代码正在创建一个新数组并复制每个项目的所有数据。如何分配一个具有最终大小的arre,然后将其填充?另外:您还应该包括您的代码。我会将方法从“创建一个空字节数组并一次添加一个字节”更改为“创建一个字节数组,它的大小取决于你的需要,然后填充它”(或者可能是“使用LINQ并直接调用ToArray”,或者“使用列表”我们需要更多的上下文。你为什么要使用
byte[]
首先?你把它称为什么?你的整个应用程序做什么?每次创建一个新数组20万次是很昂贵的。找到一种不这样做的方法将是你的解决方案。在现代C#编程中(post-.NET 4.5)我觉得在IO缓冲区之外使用原始数组都是一种代码味道。往往会有更好的集合类型更好地表示意图(例如ImmutableList、IReadOnlyList、HashSet等)
Convert.ToInt32(“0x01”,16)
应该可以正常工作。还要注意的是,在.Net Core
ToArray
中,当输入长度已知时,确实会进行优化,但是您对
ToArray
的输入是通过
Select
进行的,并且这也得到了优化。@NetMage谢谢您-我会看一看。上次我用
ToArray
检查
Select
时,只保留在中把长度放在琐碎的案例中。完全按照我的需要帮助我:)非常感谢!
var b = src.Select(s => Byte.Parse(s.AsSpan().Slice(2), System.Globalization.NumberStyles.HexNumber)).Reverse().ToArray();