2008-10-28 4 views
7

Это то, о чем я всегда задумывался, но никогда не беспокоился о профиле.Что является более эффективным способом назначения значений переменным в .NET?

Лучше ли назначать значение переменной temp, чем продолжать использовать это значение. Пример может быть яснее:

string s = reader.GetItem[0].ToString(); 
someClass.SomeField = s; 
someOtherClass.someField = s; 

ИЛИ

someClass.SomeField = reader.GetItem[0].ToString(); 
someOtherClass.someField = reader.GetItem[0].ToString(); 

Моя первая мысль была бы верхний пример будет более эффективным, поскольку он не имеет доступа к коллекции товара или позвоните ToString.

Было бы интересно услышать идеи других народов или окончательный ответ в любом случае.

ответ

15

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

Итак, если вы, программист, знаете, что эти вызовы чисты/идемпотентны, тогда вы должны написать код первым способом.

0

Ну, полагая, что функция ToString не просто передает ссылку на какой-либо предварительно сделанный внутренний объект, должно быть довольно ясно, что первая версия, где выполняется только один вызов, будет самой быстрой. Однако, если это проблема производительности, о которой вы должны заботиться или нет, это совершенно другая история.

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

6

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

Однако, как и более эффективный, первый способ лучше указывает на намерение - вы имеете в виду присвоить одно и то же значение двум вещам. Это также помогает ремонтопригодности, потому что, если это необходимо изменить, вам нужно только изменить его в одном месте. Для меня оба они, как правило, важнее эффективности.

+0

Некоторые, вероятно, скажут, что они ненавидят это, но я часто буду делать следующее, чтобы было ясно, что несколько переменных инициализируются с тем же значением. oneVar = anotherVar = someFunctionCall(); – grantwparks 2009-09-19 22:53:44

+0

Какие языки .net являются юридическими? – recursive 2009-09-19 23:21:57

+0

Это действительно в C# как минимум. Я разделен на предложение от @grantwparks - с одной стороны, он очень прямо выражает намерение инициализировать оба значения до одного значения. С другой стороны, мне всегда не нравилась практика, которую трудно было прочитать. Пища для размышлений ... – Bevan 2009-09-19 23:52:11

0

У меня только есть привычка хранить значение в локальной переменной, если я буду использовать его более одного раза. Обычно, однако, это потому, что я предпочитаю компактность кода, а не слишком озабочен эффективностью - хотя, я бы определенно сделал это, если многократно использовал его в цикле.

Иногда я несовместим и просто перепечатываю, особенно если просто использую аксессуар и не вызываю метод, требующий вычисления.

0

Это мое правило. В случае сомнений, profile your code. Оптимизирующий компилятор может удалить много кода, что ускорит выполнение кода.

Два факты также должны быть рассмотрены:

  • .NET выделяет память очень быстро.
  • Чрезмерный мусор может замедлить ваше приложение из-за дополнительных сбоев страницы, плохой локальности ссылок, чрезмерной сборки мусора.

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

0

Вопросы читаемости. Какова польза переменной s с именем?

Кроме того, вместо использования [0] имя поля будет иметь больше смысла.

2

Существует еще один вариант - составное присваивание:

someOtherClass.someField = someClass.SomeField = reader.GetItem[0].ToString(); 

При этом использование компилятор будет оценивать reader.GetItem[0].ToString()раз, и использовать его для назначения обоих членов (это не использовать get из someClass). Это делается путем дублирования значения в стеке (для которого не требуется явный локальный).

Очень эффективный, но, честно говоря, я не стал бы слишком волноваться по поводу оригинала с переменной.

0

Есть и другие вопросы, которые следует учитывать. Если использование s для назначения другим переменным отделяется от того, где s инициализируется более чем двумя строками кода, вы открываете возможность того, что кто-то еще придет и добавит код позже, который изменяет значение s между его использует или как-то ветви вокруг исходного задания на s.

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

Существует фракция в программировании, которая верит в «программирование без переменных» (в отличие от знаменитой статьи «без программирования» десятилетия назад). Например, XSL, в то время как у него есть «переменные», они не изменяются после их первоначального назначения в пределах одной области. Это, по мнению некоторых, это то, что помогает гарантировать отсутствие непредвиденных побочных эффектов.

Смежные вопросы