Почему foreach быстрее, чем для цикла при чтении строк richtextbox
Существует два способа чтения данных из RichTextBox по строкам
1) используйте цикл for для прокрутки строк richtextBox
String s=String.Empty;
for(int i=0;i<richtextbox.lines.length;i++)
{
s=richTextBox.Lines[i]
}
2) используйте цикл foreach для перечисления коллекции richTextBox.Lines
String s=String.Empty;
foreach(string str in txtText.Lines)
{
s=str;
}
Существует огромная разница в производительности, когда мы используем цикл foreach для перечисления коллекции массивов для richtextbox.
Я пробовал с 15000 строк. Для цикла было занято 8 минут, чтобы просто выполнить цикл до 15000 строк. В то время как foreach взял долю секунды, чтобы перечислить его.
Почему такое поведение существует?
Ответы
Ответ 1
Как отметил Мехрдад, доступ к свойству Lines
занимает много времени. Вы должны быть осторожны здесь - вы обращаетесь к нему дважды на каждой итерации на данный момент:
String s = String.Empty;
for (int i = 0; i < richTextBox.Lines.Length; i++)
{
s = richTextBox.Lines[i];
}
Даже если вы удалите доступ в теле цикла следующим образом:
String s = String.Empty;
for (int i = 0; i < richTextBox.Lines.Length; i++)
{
}
вы по-прежнему получаете доступ к Lines
на каждой итерации, чтобы убедиться, что вы закончили!
Если вы не хотите foreach
, вы можете просто выбрать Lines
один раз:
string[] lines = richTextBox.Lines;
for (int i = 0; i < lines.Length; i++)
{
s = lines[i];
}
Лично я предпочитаю foreach
, если вам действительно нужен индекс:)
Ответ 2
Я думаю, что свойство Lines
пересчитывается каждый раз, когда вы хотите получить к нему доступ. Следовательно, метод foreach
выполняет вычисления только один раз, а каждый раз, когда ваша ссылка Lines[i]
пересматривает все это. Попробуйте кэшировать результат свойства Lines
и снова проверить:
String s = String.Empty;
var lines = richtextbox.Lines;
for(int i = 0; i < lines.Length; i++)
{
s = lines[i];
}
Кстати, ваш вопрос делает неявное предположение, что foreach
всегда медленнее, чем for
. Это не всегда так.
Ответ 3
Возможно, потому что для поиска следующей строки в текстовом поле требуется время. Когда вы используете случайный доступ путем индексации в первом случае, он должен найти эту строку с нуля. Когда итерация выполняется внутри foreach
, она может сохранять состояние и быстро находить следующую строку.
Это должно сделать первый случай в O (n ^ 2), а второй - в O (n).
Ответ 4
Может ли быть, что каждая строка копируется в новую строковую переменную (str) в каждом цикле? Я здесь, но вы, вероятно, можете проверить теорию с помощью этого кода
String s = String.Empty;
for (int i = 0; i < richTextBox.Lines.Length; i++)
{
string str = richTextBox.Lines[i];
s = str;
}
Ответ 5
.NET Reflector очень полезно определить , почему вы видите производительность, чего вы не ожидаете.
Попробуйте посмотреть на аксессуар Lines
get
, чтобы узнать, что он на самом деле делает каждый раз, когда вы обращаетесь к нему.