Инициализировать поля класса в конструкторе или в декларации?

голоса
326

Я программирование в C # и Java в последнее время и мне интересно, где лучшее место, чтобы инициализировать свои поля класса.

Должен ли я сделать это при объявлении ?:

public class Dice
{
    private int topFace = 1;
    private Random myRand = new Random();

    public void Roll()
    {
       // ......
    }
}

или в конструкторе ?:

public class Dice
{
    private int topFace;
    private Random myRand;

    public Dice()
    {
        topFace = 1;
        myRand = new Random();
    }

    public void Roll()
    {
        // .....
    }
}

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

Задан 23/08/2008 в 20:59
источник пользователем
На других языках...                            


14 ответов

голоса
239

Мои правила:

  1. Не инициализировать значения по умолчанию в объявлении ( null, false, 0, 0.0...).
  2. Предпочитают инициализации в декларации, если у вас нет параметра конструктора, который изменяет значение поля.
  3. Если значение поля изменяется из-за параметра конструктора положить инициализации в конструкторах.
  4. Будьте последовательны в своей практике (самое важное правило).
Ответил 23/08/2008 в 21:04
источник пользователем

голоса
132

В C # это не имеет значения. Два образца кода вы даете совершенно эквивалентны. В первом примере компилятор С # (или это CLR?) Построит пустой конструктор и инициализирует переменные, как если бы они были в конструкторе. Если уже есть конструктор, то любая инициализация «выше» будет перемещен в вершину.

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

Ответил 24/08/2008 в 17:04
источник пользователем

голоса
13

Семантика C # несколько отличается от Java здесь. В C # назначение в объявлении выполняется перед вызовом конструктора суперкласса. В Java это делается сразу же после того, что позволяет «это» будет использоваться (особенно полезно для анонимных внутренних классов), и означает, что семантика этих двух форм действительно матч.

Если вы можете, сделать поля окончательным.

Ответил 05/09/2008 в 21:22
источник пользователем

голоса
11

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

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

Ответил 10/11/2013 в 23:56
источник пользователем

голоса
5

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

  • Поля в статических классов / методов
  • Поля набраны как статические / заключительный / др

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

Ответил 23/08/2008 в 22:56
источник пользователем

голоса
3

Что делать, если я сказал вам, это зависит?

Я вообще инициализировать все и делать это на постоянной основе. Да, это слишком явно, но это также немного легче поддерживать.

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

В реальной системе время, я вопрос, если я даже нужна переменная или константа при всех.

И в C ++ я часто рядом нет инициализации в любом месте и переместить его в функцию Init (). Зачем? Ну, в C ++, если вы инициализация то, что может вызвать исключение во время строительства объекта вы открываете себя к утечкам памяти.

Ответил 23/08/2008 в 23:09
источник пользователем

голоса
2

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

Ответил 17/01/2016 в 20:01
источник пользователем

голоса
2

Есть много и различных ситуаций.

Мне просто нужно пустой список

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

public class CsvFile
{
    private List<CsvRow> lines = new List<CsvRow>();

    public CsvFile()
    {
    }
}

Я знаю, что значения

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

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = new List<string>() {"usernameA", "usernameB"};
    }
}

или

public class AdminTeam
{
    private List<string> usernames;

    public AdminTeam()
    {
         usernames = GetDefaultUsers(2);
    }
}

Пустой список с возможными значениями

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

public class AdminTeam
{
    private List<string> usernames = new List<string>();

    public AdminTeam()
    {
    }

    public AdminTeam(List<string> admins)
    {
         admins.ForEach(x => usernames.Add(x));
    }
}
Ответил 14/08/2015 в 13:26
источник пользователем

голоса
1

Будучи последовательным является важным, но это вопрос, чтобы спросить себя: «У меня есть конструктор для чего-нибудь еще»

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

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

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

Ответил 24/05/2017 в 20:27
источник пользователем

голоса
1

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

Существует также вопрос о согласованности со статической инициализации поля, которое должно быть инлайн для лучшей производительности. Дизайн Руководство Рамочного для Конструктора Design сказать:

✓ СЧИТАЮТ инициализации статических полей рядный, а не в явном виде с использованием статических конструкторов, потому что среда способна оптимизировать производительность типов, которые не имеют явно определенный статический конструктор.

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

Ответил 14/05/2017 в 05:46
источник пользователем

голоса
1

Существует небольшое преимущество производительности для установки значения в объявлении. Если вы установите его в конструкторе он фактически устанавливается дважды (первый к значению по умолчанию, а затем сбрасывается в CTOR).

Ответил 29/08/2008 в 16:47
источник пользователем

голоса
0

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

class MyGeneric<T>
{
    T data;
    //T data = ""; // <-- ERROR
    //T data = 0; // <-- ERROR
    //T data = null; // <-- ERROR        

    public MyGeneric()
    {
        // All of the above errors would be errors here in constructor as well
    }
}

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

class MyGeneric<T>
{
    T data = default(T);

    public MyGeneric()
    {           
        // The same method can be used here in constructor
    }
}
Ответил 08/07/2018 в 12:32
источник пользователем

голоса
0

Рассмотрим ситуацию, когда у вас есть более чем один конструктор. Будет ли инициализация отличаться для различных конструкторов? Если они будут такими же, то зачем повторять для каждого конструктора? Это в соответствии с KOKOS заявление, но не могут быть связаны с параметрами. Скажем, к примеру, вы хотите сохранить флаг, который показывает, как был создан объект. Тогда этот флаг будет инициализирован по-разному для разных конструкторов, независимо от параметров конструктора. С другой стороны, если вы повторите ту же инициализацию для каждого конструктора вы оставляете возможность того, что вы (непреднамеренно) изменить параметр инициализации в некоторых конструкторах, но не в других. Таким образом, основная концепция здесь является то, что общий код должен иметь общее расположение, а не потенциально повторяться в разных местах.

Ответил 20/10/2017 в 21:05
источник пользователем

голоса
0

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

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

Ответил 24/08/2008 в 16:59
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more