从以下测试来看,for 的效率更高:(以毫秒为单位,相差 +-3 毫秒 - 这微不足道..)
var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Range(0, 4).Select(i => string.Empty).ToArray();
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //3305
watch = System.Diagnostics.Stopwatch.StartNew();
var stringArray2 = new string[4];
for (int i = 0; i < stringArray2.Length; i++)
{
stringArray2[i] = string.Empty;
}
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //1
但您可以使用.Repeat 代替Enumerable.Range().Select:
var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Repeat(string.Empty, 4).ToArray();
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //391
在说完上面的通知之后,你在这里谈论的是非常小的集合(4 项)。在较大的集合中,特别是如果您删除 .ToArray(),它的行为就不一样了:
var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Repeat(string.Empty, 100000);
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //360
watch = System.Diagnostics.Stopwatch.StartNew();
var stringArray2 = new string[100000];
for (int i = 0; i < stringArray2.Length; i++)
{
stringArray2[i] = string.Empty;
}
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //1335
但我担心最后的 Select 可能会循环两次
查看Reference Source,.Range 和Repeat 都是用yield return 实现的:
static IEnumerable<int> RangeIterator(int start, int count) {
for (int i = 0; i < count; i++) yield return start + i;
}
所以它也是延迟执行的,就像.Select 意味着它不会循环两次。
并不是说使用Stopwatch 每次运行都会返回不同的结果,但总体思路如上所示
IMO,尤其是在小型集合的情况下,为了提高可读性而不是这些微小的性能改进。当您已经遇到性能问题时,只有在获得更大的鱼之后(例如在List<> 上嵌套for 循环而不是使用HashSet<>),才可以处理这样的事情。