2009-03-11 2 views
33

Код стиль вопрос здесь.Должен ли я всегда/никогда/никогда не инициализировать поля объектов значениями по умолчанию?

Я просмотрел вопрос this, который спрашивает, действительно ли .NET CLR всегда будет инициализировать значения полей. (Ответ да.) Но мне кажется, что я не уверен, что это всегда хорошая идея, чтобы он это делал. Мое мышление является то, что если я вижу, как это заявление:

int myBlorgleCount = 0; 

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

int myBlorgleCount; 

У меня нет реальной непосредственной идеи, если 0 является законным или разумным значением. И если программист только начинает читать и модифицирует его, я не знаю, должен ли программист начать его использовать до того, как он установит для него значение, или если они ожидали, что он будет равен нулю и т. Д.

другой стороны, некоторые довольно умные люди и утилита очистки кода Visual Studio, скажите мне удалить эти избыточные объявления. Каков общий консенсус по этому поводу? (Есть ли консенсус?)

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

EDIT: Хотя я и сказал, что этот вопрос является агностиком языка, он явно не применим к таким языкам, как C, где инициализация значения не выполняется.

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

ответ

24

Подумайте, долгосрочное обслуживание.

  • Храните код как можно более ясным.
  • Не полагайтесь на определенные пользователем способы инициализации, если вам это не нужно. Может быть, более новая версия языка будет работать по-другому?
  • Будущие программисты будут вам благодарны.
  • Руководство будет вам благодарно.
  • Зачем обманывать вещи даже малейшим?

Обновление: Будущие сопровождающие могут происходить из другого фона. Речь идет не о том, что «правильно», а в том, что будет проще всего в долгосрочной перспективе.

+5

Для будущих сопровождающих: в первый день они спрашивают, скажите им, в каком мире они находятся. Конец проблемы. И мы говорим не о языковой функции. Это функция _platform_. Это верно для evey .NET language и всегда будет правдой.* Подумайте, что произойдет, если это изменится! –

+2

На самом деле это не так. Не все программное обеспечение является .NET? Или я живу в параллельной вселенной? –

+3

Джон: Сопровождающий может прекрасно понять проблему, но как они знают, что кодер хотел получить значение по умолчанию, когда они не инициализировали значение? Возможно, он должен был быть дефолтом, но, возможно, нет. В конце концов, если бы все было идеально с кодом, они не поддержали бы его. – Beska

0

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

В более старых и неизмененных языках ожидается, что значение неизвестно. Это ожидание сохраняется программистами, поступающими с этих языков.

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

На данный момент я думаю, что это прекрасно, чтобы инициализировать значение; то, что когда-то было имплицитно, становится явным. В долгосрочной перспективе, скажем, в ближайшие 10-20 лет люди могут начать изучать, что значение по умолчанию возможно, ожидается и известно, особенно если они остаются согласованными между языками (например, пустая строка для строк, 0 для чисел) ,

+0

За исключением некоторых языков, таких как Java, пустая строка, "", на самом деле является строкой. Вместо этого вы должны инициализировать переменную String равной нулю, чтобы не создавать объект String без необходимости. –

+0

Yup, точно моя точка: прямо сейчас, значения по умолчанию почти наверняка на разных языках. :) –

+0

@ Давид, то же самое верно в C#. (Если вы пишете 'var x =" ";' вы только что создали новый строковый объект.) – ricovox

2

Я согласен с тобой; это может быть многословным, но я хотел бы видеть:

int myBlorgleCount = 0; 

Теперь я всегда начальные строки, хотя:

string myString = string.Empty; 

(. Я просто ненавижу пустые строки)

4

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

В C# нет никаких накладных расходов, поскольку значения все инициализируются в любом случае. В C/C++ неинициализированные значения будут содержать значения мусора/неизвестные (все, что было в ячейке памяти), поэтому инициализация была более важной.

+0

FxCop имеет правило в разделе Performance, которое специально вызывает ненужную инициализацию. Должны быть какие-то отходы, если они скажут вам не делать этого. Не то, чтобы это имело значение в большинстве реальных приложений ... – Pedro

+1

Точно ... мой инструмент проверки кода имеет аналогичное правило. Но я не совсем понимаю, почему ... тем более, что мне сказали (но еще не подтвердили), что он обычно не делает никаких отходов ... что избыточная инициализация оптимизирована. – Beska

13

Вы всегда в безопасности, полагая, что платформа работает так, как работает платформа. Платформа .NET инициализирует все поля значениями по умолчанию. Если вы видите поле, которое не инициализировано кодом, это означает, что поле инициализируется средой CLR, но не является неинициализированной.

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


Другой ненужным пережитком прошлого является следующее:

string foo = null; 
foo = MethodCall(); 

Я видел, что у людей, которые должны знать лучше.

+0

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

+2

В C# (и, вероятно, VB.NET) компилятор выдает ошибку, если вы попытаетесь прочитать переменную, которая никогда не была установлена ​​в коде. Это само по себе предотвращает такую ​​ситуацию, как вы описываете, поскольку переменная всегда должна быть задана где-то до чтения из нее, даже если она не указана. – Chris

+1

Вам не хватает значения, которое всегда задано при любых обстоятельствах. Нет смысла воображать, что может произойти что-то другое. Это никогда не может быть ошибкой, если вы не имеете дело с действительно глупым разработчиком, который ожидает «int i»; для инициализации до 1. Огонь его, проблема решена. –

0

Вы должны это сделать, нет необходимости, но это лучше, если вы это сделаете, потому что вы никогда не знаете, использует ли язык, который вы используете, для инициализации значений. Выполняя это самостоятельно, вы гарантируете, что ваши значения будут инициализированы и будут установлены стандартные предопределенные значения. Нет ничего плохого в этом, кроме, быть может, немного «потраченного времени». Я бы рекомендовал его сильно. Хотя похвала Джона довольно информативна, при общем использовании лучше идти безопасным путем.

+0

Поскольку он говорил о .NET, оставляя избыточные инициализации _is_ безопасным путем, поскольку поля всегда инициализируются. Если он не использует .NET, то ответ зависит от платформы. В случае неуправляемого C/C++ это необходимо. –

0

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

0

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

4

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

Но я думаю, что это общая проблема со всеми языковыми функциями. Мое мнение о том, что это: Если это официальная функция языка, вы можете использовать его. (Конечно, есть некоторые анти-функции, которые следует использовать с осторожностью или избегать вообще, как отсутствующего option explicit в Basic или алмазным наследования Визуальный в C++)

Был я раз, когда я был параноиком и добавил все виды ненужных инициализаций, явные приведения, über-параноидальные блоки try-finally, ... Я даже подумал об игнорировании автоматического бокса и замене всех вхождений явными преобразованиями типа, просто «чтобы быть в безопасности».

Проблема: нет конца. Вы можете избежать почти всех функций языка, потому что вы не хотите доверять им.

Помните: Это только магия, пока не понял :)

+1

Извините, но я беру вопрос: «Если это официальная функция языка, вы должны использовать его». Наследование Diamond на C++ делает замечательный контрапункт, только для начала. –

+1

Да, я понимаю, что вы имеете в виду, но я думаю, что это чрезмерно интерпретирует предложение. Конечно, не всегда хорошо делать все возможное. Во всяком случае, я изменил его на «can». –

+0

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

0

Это помечено как язык-агностик, но большинство из ответов на этот вопрос в отношении C#.

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

+1

Он спрашивает о языках .net, где гарантируется инициализация. – Ray

+0

Ну, а не .NET обязательно, но любой язык, на котором гарантируется какая-то инициализация по умолчанию. Вопрос в том, что, несмотря на эту гарантию, должно ли значение быть специально инициализировано в любом случае? – Beska

0

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

1

В том случае, когда я не могу сразу установить его на что-то полезное

int myValue = SomeMethod(); 

обращу его в 0. То есть больше, чтобы избежать того, чтобы думать о том, какое значение будет иначе. Для меня тот факт, что целые числа всегда устанавливается на 0 не на кончик моих пальцев, так что, когда я вижу

int myValue; 

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

int myValue = 0; 

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

Так делайте, что когда-либо имеет смысл как для вас, так и для команды, в которой вы работаете. Если обычной практикой является ее установка, тогда установите ее, иначе нет.

0

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

public int Count { get; set; } 
1

По моему опыту я обнаружил, что явным инициализации локальные переменные (в .NET) добавляют больше беспорядка, чем ясность.

Переменные класса, с другой стороны, всегда должны быть инициализированы. В прошлом мы определяли общесистемные пользовательские «нулевые» значения для общих типов переменных. Таким образом, мы всегда могли знать, что было неинициализировано по ошибке и что было инициализировано специально.

1

Я всегда инициализирую поля явно в конструкторе. Для меня это место.

0

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

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

Чтобы использовать грубую аналогию, рассмотрим следующие два условия: (! Xposition = 0)

  1. `, если ...
  2. `, если (! (Флаги & WoozleModes.deluxe) = 0) ...

В первом случае сравнение с буквальным нулем имеет смысл, поскольку оно проверяет позицию, которая семантически не отличается от любой другой. Однако во втором сценарии я бы предположил, что сравнение с литеральным нулем ничего не добавляет к удобочитаемости, поскольку код действительно не интересует, является ли значение выражения (flags & WoozleModes.deluxe) числом, отличным от нуля, а скорее, непустой».

Я не знаю каких-либо языков программирования, которые предоставляют отдельные способы выделения числовых значений для «нуля» и «пустых», за исключением того, что не требуют использования буквальных нулей при указании пустоты.

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