2010-11-18 1 views
5

, какая декларация/описание лучше и ПОЧЕМУ?Создайте объект в конструкторе или в верхней части класса

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow() 
    { 
     _test = new Test(); 
    } 
} 

ИЛИ

public class MainWindow 
{ 
    private Test _test = new Test(); 

    public MainWindow() 
    { 

    } 
} 
+1

Дубликат дубликата .... См. Http://stackoverflow.com/questions/298183/c-member-variable-initialization-best-practice – Tony

ответ

2

Задайте себе этот вопрос: что произойдет, если вы добавите другие конструкторы в MainWindow? Вы хотите, чтобы потом помнить, чтобы ссылаться на другие конструкторы, чтобы убедиться, что _test правильно инициализирован? Или это нормально для _test, чтобы не инициализироваться, если используется другой конструктор?

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

0

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

2

я бы пойти на третий вариант:

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow(Test test) 
    { 
     _test = test; 
    } 
} 

Вводя зависимость вам сделать ваш код проще для модульного тестирования.

+0

OP имел '_test' как переменную-член класс, что означает, что его нельзя тестировать отдельно от «MainWindow», вместо этого тест должен быть нацелен на «MainWindow». IOW: IoC не подходит для '_test'. – slugster

+0

Этот способ позволяет вам издеваться над этим при тестировании. –

+0

@slugster: Это зависит от того, что делает Тест. Он ДОЛЖЕН вводиться, если он предоставляет любые данные для MainWindow. Вы получаете предопределенный (проверяемый) результат, если вы можете предоставить эти данные из своего теста (через заглушку/издевавшийся объект) – jgauffin

1

Это так же, как разница между

int i; 
... 
i = 0; 

и

int i = 0; 

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

2

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

Вообще, хотя это вопрос вкуса, а самое главное - быть соответствует по вашему выбору.

1

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

+0

+1: ленивый экземпляр может быть действительно полезным. – Tony

+0

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

0

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

Нет параметров

public class MainWindow 
{ 
    private Test _test = new Test(); 

    public MainWindow() 
    { 

    } 
} 

с параметрами:

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow() 
    { 
     _test = new Test("abc") 
    } 
} 

Как Джексон Папа сказал, что не может быть хорошей идеей, чтобы добавить конструктор для объекта, чтобы сделать его проще начать использовать Впоследствии Д.И. Вы можете прочитать о DI/IoC здесь: http://www.codeproject.com/KB/architecture/DependencyInjection.aspx

0

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

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

Например:

public class MainWindow 
{ 
    private Test _test; 

    public MainWindow(int i) 
    { 
     _test = new Test(i); 
    } 
} 
0

Он не делает разницы вообще, потому что компилятор генерирует точно тот же IL. С точки зрения удобочитаемости это вопрос личного вкуса. Я предпочитаю второй вариант, но с модификатором readonly:

public class MainWindow 
{ 
    private readonly Test _test = new Test(); 

    public MainWindow() 
    { 

    } 
} 

Это особенно легче читать и поддерживать, когда класс имеет более одного конструктора.

+0

В данном примере это правда, но когда 'MainWindow' будет получен из какого-либо другого класса, есть разница: во втором случае' Test' будет построен _before_ базовый конструктор. – Vlad