Подтвердить что ты не робот

Почему 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 взял долю секунды, чтобы перечислить его.

Почему такое поведение существует?

4b9b3361

Ответ 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, чтобы узнать, что он на самом деле делает каждый раз, когда вы обращаетесь к нему.