Где правильнее выполнять установку значения свойства, в сеттере или в конструкторе класса?

public abstract class Parser
{
    protected List<string> Tables { get; set; }
    protected string TableName { get; }
    public List<List<object>> Table { get; protected set; }

    public Parser()
    {
        Tables = GetListOfTables();
        Program.PrintCollection(Tables);
        TableName = Program.GetUserChoose(Tables);
        Table = GetTable();
    }

    protected abstract List<string> GetListOfTables();
    protected abstract List<List<object>> GetTable();
}

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


Ответы (2 шт):

Автор решения: iiKuzmychov

Не существует "правильного способа" установления значений свойствам.

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

→ Ссылка
Автор решения: Kalmankantaja

Я согласен с ответом @iiKuzmychov, но не до конца. Иногда бывают классы, которые без каких-либо данных не имеют смысла, так же преимущество конструктора перед set - вызов каких либо методов в этом конструкторе (что очень нежелательно, но всё же). Помимо вызова чего-либо проверять на валидность данных тоже лучше делать в конструкторе, нежели в set, т.к придётся делать backing field (можете сами посмотреть на читаемость кода с проверкой в set и конструкторе). Смысл конструктора - инициализировать объект, не больше.

class File
{
   public File(string path)
   {
       if(string.IsNullOrEmpty(path))
         throw new ArgumentNullException();

       Path = path;
   }
   public string Path { get; set; }
}

В C# 9 добавили init свойства и это работает следующим образом:

class MyClass //Можно использовать record
{ 
   public int MyIntProperty { get; init; }
}
var myClass = new MyClass() { MyIntProperty = 5 };
→ Ссылка