我不喜欢过早优化,但在做一个简单的任务时我很好奇 所以我添加了一个秒表。 我不明白这种差异有多大。
每个字符串数组(7个字符)[richtextbox.text]。
阵列长度:5500个元素。
Foreach Elapsed Time: 0.0015秒
经过时间: 9.757秒
有关:
if (chkLineBreaks.Checked)
{
for (int i = 0; i < txtInput.Lines.Length; i++)
{
outputStringBuilder.Append($@"'{txtInput.Lines[i]}',");
}
}
FOREACH:
foreach (var line in txtInput.Lines)
{
outputStringBuilder.Append($@"'{line}',");
if (chkLineBreaks.Checked)
outputStringBuilder.AppendLine();
}
从我所看到的,差异应该可以忽略不计,For会略快一些。
更重要的是,foreach在每次迭代中都有一个条件(除非它在循环之前被'提升'。
这里发生了什么?
编辑: 我已将foreach代码更改为:
int i = 0;
foreach (var line in txtInput.Lines)
{
outputStringBuilder.Append($@"'{txtInput.Lines[i]}',");
i++;
}
所以它现在正在做同样的事情。 它需要 4.625秒 ..仍然是FOR
的一半时间另外我知道我可以在循环外提取数组但这不是我在这里测试的内容:)
编辑#2: 这是该部分的完整代码:
Stopwatch sw = new Stopwatch();
sw.Start();
// for (int i = 0; i < txtInput.Lines.Length; i++)
// {
// outputStringBuilder.Append($@"'{txtInput.Lines[i]}',");
// }
int i = 0;
foreach (var line in txtInput.Lines)
{
outputStringBuilder.Append($@"'{txtInput.Lines[i]}',");
i++;
}
MessageBox.Show(sw.Elapsed.ToString());
答案 0 :(得分:3)
问题是txtInput.Lines
在for
循环中执行多次(每行一次)(由于使用了txtInput.Lines[i]
)。 因此,对于文件的每一行,您都说'好,请将此文本框解析为多行 - 然后将第n行解析为' - 并且解析是杀手位。
为了更公平的比较:
if (chkLineBreaks.Checked)
{
var lines = txtInput.Lines;
for (int i = 0; i < lines.Length; i++)
{
outputStringBuilder.Append($@"'{lines[i]}',");
}
}
这样Lines
调用只执行一次(即相当于foreach
场景)。
发现这类问题的一种方法是比较时间。较慢的一个比快速的慢约6K,你有5.5K的条目。由于5.5K和6K是非常相似的数字,它可能会促使你思考'我在循环中做了什么我不应该做的事情?'
答案 1 :(得分:1)
编译代码在遍历数组(或列表)时,for
和foreach
语句之间的差别很小。
考虑这个简单的代码,用三种不同的方式写出字符串列表:
class Program
{
static void Main(string[] args)
{
var list = Enum.GetNames(typeof(System.UriComponents));
// 1. for each
foreach (var item in list)
{
Console.WriteLine(item);
}
// 2. for loop
for (int i = 0; i<list.Length; i++)
{
Console.WriteLine(list[i]);
}
// 3. LINQ
Console.WriteLine(string.Join(Environment.NewLine, list));
}
}
现在查看MSIL
已编译的代码,使用C#
或ILSpy
将其翻译回DotNetPeek
。
// ConsoleApplication1.Program
private static void Main(string[] args)
{
string[] list = Enum.GetNames(typeof(UriComponents));
string[] array = list;
for (int j = 0; j < array.Length; j++)
{
string item = array[j];
Console.WriteLine(item);
}
for (int i = 0; i < list.Length; i++)
{
Console.WriteLine(list[i]);
}
Console.WriteLine(string.Join(Environment.NewLine, list));
}
请参阅两个for循环。 foreach
语句由编译器变为for
循环。至于string.Join()
语句,它调用SZArrayEnumerator
来保存对数组的引用,以及当前索引值。在每次.MoveNext()
调用时,索引会递增并返回一个新值。基本上,它等同于以下内容:
int i = 0;
while (i<list.Length)
{
Console.WriteLine(list[i]);
i++;
}