Сведения о вопросе

Life

07:29, 4th August, 2020

Теги

c#   java    

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

Просмотров: 510   Ответов: 8

Я недавно программировал в 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()
    {
        // .....
    }
}

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



  Сведения об ответе

baggs

21:06, 1st October, 2020

Мое правило:

  1. Не инициализируйте со значениями по умолчанию в объявлении ( null , false , 0 , 0.0 ...).
  2. Предпочитайте инициализацию в объявлении, если у вас нет параметра конструктора, который изменяет значение поля.
  3. Если значение поля изменяется из-за параметра конструктора, поместите инициализацию в конструкторы.
  4. Будьте последовательны в своей практике (самое главное правило).


  Сведения об ответе

ЯЯ__4

15:59, 6th August, 2020

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

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


  Сведения об ответе

crush

20:24, 13th August, 2020

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

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


  Сведения об ответе

PIRLO

22:30, 29th August, 2020

Я думаю, что есть один нюанс. Однажды я допустил такую ошибку: внутри производного класса я попытался создать "initialize at declaration" полей, унаследованных от абстрактного базового класса. В результате оказалось, что существует два набора полей, один из которых является "base", а другой-недавно объявленные, и это стоило мне довольно много времени для отладки.

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


  Сведения об ответе

ЯЯ__4

23:10, 1st August, 2020

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

  • Поля в статических классах / методах
  • Поля, набранные как static/final/et al

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


  Сведения об ответе

ASER

18:16, 26th August, 2020

А что, если я скажу тебе, это зависит от обстоятельств?

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

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

В системе реального времени я сомневаюсь, нужна ли мне вообще переменная или константа.

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


  Сведения об ответе

lesha

12:12, 14th August, 2020

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

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

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

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));
    }
}


  Сведения об ответе

$DOLLAR

22:21, 7th August, 2020

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться