繁体   English   中英

Array.ForEach()与C#中的循环标准相比如何?

[英]How does Array.ForEach() compare to standard for loop in C#?

作为一名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和泛型来引入不必要的开销?

谢谢,戴夫

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);

这应该是一个非常快速的选择,因为它基本上就是你现在正在做的事情。

第二种方法使用委托来设置每个字节,这意味着对数组中的每个字节都有一个方法调用。 设置一个字节只需要很多开销。

另一方面,普通循环由编译器很好地优化。 它将确定索引不能在数组之外,因此它将跳过边界检查。

澄清一下:你根本就没有使用LINQ。 ForEach方法是Array类中的一个方法,它早于添加LINQ。

当我想要memset / memcpy类型行为时,我倾向于使用Buffer.BlockCopy 我会测量性能并使用反射器之类的东西。 可能是内部语言调用内置类,而内置类又是MEMCPY和MEMSET的薄包装器。

如果你的表现就像发布CAbott提到的问题的人那样,你可能想看看我刚刚在那里发布的答案

除非你在非常严格的性能操作中这样做,否则你不会遇到问题。 关于foreach调用与索引迭代有很多基准测试,差异很小。

当然,你总是可以自己对它进行基准测试......

我不认为仿制药会对性能产生不利影响。 它们主要在编译时处理,它们的一般目的是消除在对象和所需类型之间进行转换的需要,这种类型最不会产生可忽略的影响,并且最多会导致可测量的性能增益。

至于LINQ,我不确定它可以带来什么性能影响。

但最终,初始化是一项次要任务,性能影响将无关紧要。

我发现如果你把它们放在一个关键的执行路径中,那么Array.ForEach要比for或foreach循环慢得多。 但是,除非您是框架/库开发人员或实际需要初始化数百万个数组,否则我根本不担心性能。 通过在其他地方进行优化,您很可能获得更多收益。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM