作为一名C程序员,我可以输入:
memset( byte_array, '0xFF' );
并获取一个填充'FF'字符的字节数组。所以,我一直在寻找替代品:
for (int i=0; i < byteArray.Length; i++)
{
byteArray[i] = 0xFF;
}
最近,我一直在使用一些新的C#功能,并且一直在使用这种方法:
Array.ForEach<byte>(byteArray, b => b = 0xFF);
当然,第二种方法似乎更清晰,更容易看到,但性能与使用第一种方法相比如何呢?我是否通过使用Linq和泛型来引入不必要的开销?
谢谢, 戴夫
答案 0 :(得分:7)
Array.ForEach<byte>(byteArray, b => b = 0xFF);
这没有任何作用。它将每个字节的副本设置为0xFF,它永远不会在数组中设置。
为了更简单地执行此操作,您可以尝试
Enumerable.Repeat((byte)0xFF, someCount).ToArray();
初始化数组
重复肯定会慢于你的for循环。根据CAbbott在评论中发布的链接,在一个拥有超过一百万个项目的阵列上,它慢了大约10.5秒(12.38对1.7),但如果你只用一小部分做了几次就没那么大的差别阵列。
你可以编写一个比Repeat和ToArray更快的简单方法,因为你可以在开始填充之前知道数组的长度。
public static T[] GetPreFilledArray<T>(T fillItem, int count)
{
var result = new T[count];
for(int i =0; i < count; i++)
{
result[i] = fillItem;
}
return result;
}
byte[] byteArray = GetPreFilledArray((byte)0xFF, 1000);
这应该是一个非常快速的选择,因为它基本上就是你现在所做的。
答案 1 :(得分:4)
第二种方法使用委托来设置每个字节,这意味着对数组中的每个字节都有一个方法调用。设置一个字节只需要很多开销。
另一方面,普通循环由编译器进行了相当好的优化。它将确定索引不能在数组之外,因此它将跳过边界检查。
澄清一下:你根本就没有使用LINQ。 ForEach方法是Array类中的一个方法,它早于添加LINQ。
答案 2 :(得分:1)
Buffer.BlockCopy。我会测量性能并使用反射器之类的东西。可能是内部语言调用内置类,而内置类又是MEMCPY和MEMSET的瘦包装。
答案 3 :(得分:1)
如果您的表现类似于发布CAbott所引用问题的人,您可能需要查看my answer I just posted there。
答案 4 :(得分:0)
除非你在非常严格的表现操作中这样做,否则你不会遇到问题。关于foreach调用与索引迭代有很多基准测试,差异很小。
当然,你总是可以自己对它进行基准测试......
答案 5 :(得分:0)
我不认为仿制药会对性能产生不利影响。它们主要在编译时处理,它们的一般目的是消除在对象和所需类型之间进行投射的需要,这种情况最坏的影响可以忽略不计,最多可以带来可衡量的性能提升。
就LINQ而言,我不确定它可以有什么性能影响。
最终,初始化是一项次要任务,性能影响无关紧要。
答案 6 :(得分:0)
如果你将它们放在一个关键的执行路径中,我发现Array.ForEach要比for或foreach循环慢得多。但是,除非您是框架/库开发人员或实际需要初始化数百万个数组,否则我根本不担心性能。通过在其他地方进行优化,您很可能获得更多收益。