2008-10-29 6 views
5

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

именно: это то, что я на основе того, что я думаю, что лучшая практика:

public class SomeClass 
{ 
    private PersonObject _person; 

    public SomeClass() 
    { 
     _person = new PersonObject("Smitface"); 
    } 
} 

против:

public class SomeClass 
{ 
    private PersonObject _person = new PersonObject("Smitface"); 

    public SomeClass() 
    { 

    } 
} 

ответ

12

Если вы установили переменную вне конструктора, тогда нет обработки ошибок (ручная обработка). Хотя в вашем примере это не имеет никакого значения, но есть много случаев, когда вы можете иметь какую-то обработку ошибок. В этом случае использование вашего первого варианта будет правильным.

Nescio рассказал о том, что подразумевалось бы на вашем приложении, если бы были какие-то ошибки конструктора.

По этой причине я всегда пользуюсь Вариантом №1.

0

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

Это личное предпочтение, они оба делают то же самое.

6

Честно говоря, если вы посмотрите на ИЛ, все, что происходит во втором случае, - это компилятор, который переводит инициализацию в конструктор для вас.

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

-3

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

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

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

+0

Ваш комментарий на самом деле не применяется здесь. Переменные инициализируются одновременно, независимо от того, какой метод используется. – Herms 2008-10-29 18:40:22

+0

Редактированный комментарий комментатора имеет хорошую точку - если у меня есть поле с инициализатором, я ЗНАЮ, что он будет инициализирован.Если у меня есть поле в классе с 20 конструкторами, сложнее убедиться, что переменная инициализирована до ее использования. Сообщение Эрика Липперта делает это еще более правдоподобным. – 2008-10-29 23:16:39

1

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

+0

, вы никогда не сможете делать предположения, глядя на конструктора, потому что язык позволяет вам делать это по-другому. что, если вы импортируете код, который вы написали в прошлом году другим способом? надеюсь, что вы не переключите шаблоны. (в этом случае кажется, что сгенерированный ИЛ эквивалентен, но может быть и другое) – 2008-10-29 18:42:13

0

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

+0

Статический конструктор? В этом примере я не вижу ничего статического. – 2008-10-29 23:05:11

0

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

Кроме того, это помогает напомнить мне о вещах, которые я хочу очистить в деконструкторе.

0

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

0

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

4

На самом деле, несмотря на то, что говорили другие, может быть Важным является ли ваша инициализация внутри или снаружи конструктора, так как при построении объекта существует другое поведение, если объект находится в иерархии (т. Е. Порядок в какие вещи запускаются, разные).

См. this post и this post от Эрика Липперта, в котором более подробно объясняется семантическая разница между ними.

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

1

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

Конечно, это имеет значение только в том случае, если нет никаких веских причин для использования инициализации конструктора (как упоминалось в описании).

2

Существует общий шаблон, называемый Injection Dependency Invertion или Inversion of Control (IOC), который предлагает именно эти два механизма для «впрыскивания» зависимого объекта (например, класса DAL) в класс, который продвигает цепочку зависимостей (furthur from the база данных)

В этой модели, используя CTOR, вы бы

общественного класса SomeClass
{
частное PersonObject за;

public SomeClass(PersonObject person) 

{  
    per = person; 
} 

}

частный PersonObject Джо = новый PersonObject ("Smitface");

SomeClass MyObj = новый SomeClass (Joe);

Теперь вы можете, например, передать в реальном классе DAL для производства вызова или класса DAL тест в методе модульного тестирования ...