Следует ли избегать инициализации в конструкторе без параметров?

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

Но стандартная инициализация объектов заранее предотвращает возникновение исключения NullReferenceException. И разве модульные тесты не предотвращают эти «трудно найти» ошибки?

Итак, как лучше всего это сделать на С#?

Что, если бы у меня был класс с 10 свойствами? Должны ли свойства также инициализироваться с помощью параметров конструктора, если я хочу избежать конструктора без параметров? Не слишком ли многословно?

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

public class UserForCreationDto
{
    public UserForCreationDto()
    {
        Username = "";
        Email = "";
    }

    [Required]
    [MaxLength(100)]
    public string Username { get; set; }

    [Required]
    [MaxLength(100)]
    public string Email { get; set; }
}

person Benjamin Martin    schedule 18.02.2020    source источник
comment
вы можете выполнить инициализацию по умолчанию в объявлении свойства public string Username { get; set; } = string.Empty;   -  person Vidmantas Blazevicius    schedule 18.02.2020
comment
Я читал, что использование or string.empty одинаково, начиная с .Net 2.0. А что, если бы у меня был класс, который состоит из этого?   -  person Benjamin Martin    schedule 18.02.2020
comment
@BenjaminMartin Почему именно вы хотите инициализировать свои свойства ""? Похоже, у вас есть случай, когда код может случайно получить доступ к свойствам до того, как они будут должным образом инициализированы. Если это произойдет, конечно, лучше знать об этом (через NRE), чем приложение продолжает функционировать, возможно, неправильно?   -  person canton7    schedule 18.02.2020
comment
@ canton7 canton7 да, я хочу предотвратить случайное исключение нулевой ссылки.   -  person Benjamin Martin    schedule 18.02.2020
comment
@BenjaminMartin Верно, похоже, вы должны последовать совету своих коллег и оставить их инициализированными до null?   -  person canton7    schedule 18.02.2020


Ответы (2)


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

public class UserForCreationDto
{
    [Required]
    [MaxLength(100)]
    public string Username { get; set; } = "";

    [Required]
    [MaxLength(100)]
    public string Email { get; set; } = "";
}

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

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

if (!string.IsNullOrEmpty(dto.Username) { ... }
person mm8    schedule 18.02.2020
comment
Учитывая имя (DTO) и показанные атрибуты, этот класс используется фреймворком, который посредством отражения будет назначать входящие данные (например, через HTTP-вызовы) этим свойствам, поэтому приватность сеттеров ничего не решит. . - person CodeCaster; 18.02.2020
comment
@CodeCaster: Это решит - предположительно неизбежно - риск получения NullReferenceException при доступе к свойству. Если свойство ссылочного типа имеет общедоступный установщик, вы никогда не можете гарантировать, что оно не null. - person mm8; 18.02.2020
comment
Если вы сделаете свойства приватными, вы, конечно, также должны добавить конструктор, который их инициализирует. В противном случае тип был бы довольно бессмысленным. - person mm8; 18.02.2020
comment
@ mm8 Но это означает, что пользователь этого класса вынужден использовать инициализацию через конструктор User (строка имени пользователя, строка адреса электронной почты). Но разве это не слишком многословно, например, для классов с 10 свойствами? - person Benjamin Martin; 18.02.2020
comment
@БенджаминМартин: Да. Я думаю, многословно это или слишком многословно. Но это единственный способ безопасно предотвратить NullReferenceException. - person mm8; 18.02.2020

Следует ли избегать инициализации в конструкторе без параметров?

другой способ спросить это

Следует избегать побочных эффектов?

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

person Kirk Horton    schedule 18.02.2020
comment
Да, но это также увеличивает сложность и объем памяти, потому что вам придется обрабатывать изменения при создании новых объектов, когда установщик свойств является закрытым. Я не вижу большой выгоды от использования этого подхода, поскольку в С# 8 есть система предупреждений (нулевые типы ссылок). В конце концов, это похоже на подход функционального программирования, позволяющий постоянно поддерживать состояние. - person Benjamin Martin; 19.02.2020