C # Лучший способ присвоения значений строкам в цикле - PullRequest
4 голосов
/ 04 июня 2009

Интересно, как наиболее эффективно назначать строковые переменные в цикле? Так, например, если мне нужно просмотреть список узлов и присвоить значение узла строке, было бы лучше, если бы я определил переменную до начала цикла, как

string myStringVariable = string.Empty
foreach(XmlNode node in givenNodes)
{
    myStringVariable = node.Value;
    ....
    ...
}

или было бы более эффективно, если бы я определял переменную внутри цикла как

foreach(XmlNode node in givenNodes)
{
    string myStringVariable = node.Value;
    ....
    ...
}

Я думаю, что первый подход более эффективен, а второй выглядит более элегантно. Есть ли разница в производительности между ними?

Спасибо за ваши ответы.

Ответы [ 7 ]

13 голосов
/ 04 июня 2009

С современными компиляторами это никак не влияет на производительность, и вы всегда должны использовать способ, который наилучшим образом соответствует вашему алгоритму. То есть предпочитайте второй вариант, если вам не нужно значение переменной из последней итерации.

6 голосов
/ 04 июня 2009

Я предполагаю, что главный вопрос: вам нужно использовать эту строковую переменную где-то ниже в вашем коде, или ее использование ограничено областью действия цикла for? Если он ограничен областью действия цикла for, определенно объявите его внутри цикла. Я сомневаюсь, что есть какое-то снижение производительности за то, что это так или иначе, но это должно быть вторичным по отношению к тому, чтобы ваши переменные были правильно распределены.

1 голос
/ 04 июня 2009

В связи с тем, что строки являются неизменяемыми, а .net работает со ссылками, производительность обоих методов не отличается.

Возможно, первый будет немного медленнее, потому что есть один (ненужный) набор myStringVariable в string.Empty. Но я думаю, что эти проблемы будут сохраняться компилятором и JIT, и поэтому нет разницы между ними в случае производительности.

И последнее, но не менее важное: разница в сфере применения. Поэтому объявите переменную в соответствующей области, где переменная необходима.

1 голос
/ 04 июня 2009

Почему бы вам не настроить небольшой тест в консольном приложении и проверить его. Я получаю очень близкие результаты для обоих методов.

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace stringtestloop
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch w = new Stopwatch();
            int itterations = 1024 * 1024 * 512;

            w.Start();
            string var1 = string.Empty;
            for (var i = 0; i < itterations; i++)
            {
                var1 = "some string";
            }
            w.Stop();

            Console.WriteLine("outside: {0} ms", w.ElapsedMilliseconds);

            w.Reset();

            w.Start();
            for (var i = 0; i < itterations; i++)
            {
                string var2 = "some string";
            }
            w.Stop();

            Console.WriteLine("inside: {0} ms", w.ElapsedMilliseconds);
            Console.ReadKey();
        }
    }
}

EDIT:

Следующий вопрос, который вы должны себе задать, это ... 536870912 (1024 *1024* 512) - это число, с которым вы собираетесь работать. Если нет, то если ваш номер будет намного меньше, тогда вы действительно не заметите разницу.

1 голос
/ 04 июня 2009

Обычно я не оптимизируюсь до этого уровня, потому что я ожидаю, что JIT-компилятор сможет выполнять такую ​​оптимизацию в любом случае во время выполнения. При этом я никогда не сравнивал их на самом деле. Конечно, если вам действительно нужна максимальная производительность, стоит протестировать ее обоими способами (с использованием достаточного количества итераций и с выпуском сборки).

1 голос
/ 04 июня 2009

Нет, между ними нет реальной разницы в производительности. Виртуальная машина распознает, что ей нужно только выделить место в стеке для одной дополнительной переменной.

0 голосов
/ 04 июня 2009

Я сомневаюсь, что есть существенное различие в производительности, поскольку в обоих случаях вы просто получаете ссылку на XmlNode.Value, а не создаете новую строку.

Тем не менее, вы обычно не должны беспокоиться об оптимизации этих случаев. Просто объявите переменную в той области, в которой она будет использоваться, и дайте компилятору проявить свою магию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...