Создание цепочки конструктора или использование именованных / необязательных параметров

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

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

 public class Student
{
    string name;
    int Id;

    public Student()
    {
    }
    public Student(string name)
    {
        this.name = name;
    }
    public Student(string name, int Id) :this(name)
    {
        this.Id = Id;

Но это явно плохо, потому что нам нужен весь код в одном конструкторе, по какой причине? Легкость чтения?

    public Student() : this(null, 0)
    { }
    public Student(string name) : this(name, 0)
    { }
    public Student(string name, int Id) 
    {
        this.name = name;
        this.Id = Id;
    }

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

    public Student(string name, int Id, string major):this(name, Id)
    {
        this.major=major;
    } 

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

Если бы я использовал именованные / необязательные параметры, это было бы еще проще.

    public Student(string name = null, int Id = 0, string major = null)
    {
        this.name = name;
        this.Id = Id;
        this.major = major;
    }

И если мне нужно другое поле, мне просто нужно отредактировать единственный конструктор. Кажется, это лучше всего соответствует принципам ООП, или я ошибаюсь? Это, по крайней мере, больше всего исключает дублирование кода. Моим заданием было «реализовать студенческий класс, следуя принципам ООП». Я знаю, что все они действительны, но является ли лучший / приемлемый способ кодирования конструкторов? Есть ли недостатки с именованными / необязательными параметрами, которые мне не хватает? Новичка очень сбивает с толку, что существует так много способов кодировать это.


person john wilkens    schedule 02.06.2016    source источник
comment
Связанные конструкторы широко использовались в C # до дополнительных опций, опциональные возможности были добавлены в C # 3.0, поэтому много информации, которую вы можете прочитать, по-прежнему использует их, потому что это старая информация, но сегодня, с необязательными параметрами, связанные конструкторы имеют теряют смысл, если в цепочке просто передаются значения по умолчанию.   -  person Gusman    schedule 02.06.2016
comment
Что сказал Гусман. Кроме того, вы можете пересылать цепочку по одному шагу за раз: public Student() : this(null) {} вместо public Student() : this(null, 0) {}. (Хотя это может стать неоднозначным, если у вас есть два конструктора, которые принимают один аргумент, допускающий значение NULL). Таким образом, вам нужно будет изменить только последний c'tor в цепочке при добавлении нового поля.   -  person Ted Hopp    schedule 02.06.2016


Ответы (4)


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

Независимые конструкторы и связанные конструкторы доступны, начиная с C # 1.0, в большинстве случаев мы используем связанные конструкторы, но иногда нам приходится использовать первые, если у двух конструкторов есть совершенно разные вещи для обработки.

class Student
{
    public Student()
    {
        DoSomething();
    }

    public Student(string name)
    {
        this.Name = name;
        DoAnotherThing();
    }
}

По сравнению с конструктором необязательных параметров эти два намного длиннее, но, честно говоря, они намного безопаснее. Рассмотрим следующий случай:

public class Student
{
    public Student(string firstName = null, string lastName = null)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

//it's working fine
//var danny = new Student("danny", "chen");

//as the business grows a lot of students need a middle name
public Student(string firstName = null, string middleName = null, string lastName = null)
{
    this.FirstName = firstName;
    this.MiddleName = middleName;
    this.LastName = lastName;
}

//for a better sequence the programmer adds middleName between the existing two, bang!

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

person Cheng Chen    schedule 02.06.2016

Я предлагаю глубже изучить это предположение:

«Но это явно плохо, потому что нам нужен весь код в одном конструкторе, по какой причине»

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

customer
    .NameOfCustomer("Shiv")
    .Bornon("12/3/1075")
    .StaysAt("Mumbai");

Иллюстративная реализация:

public class Customer
{
    public string FullName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }

    public Customer NameOfCustomer(string name)
    {
        this.FullName = name;
        return this;
    }

    public Customer BornOn(DateTime dateOfBirth)
    {
        this.DateOfBirth = dateOfBirth;
        return this;
    }

    public Customer StaysAt(string address)
    {
        this.Address = address;
        return this;
    }
} 

Пример исходного кода

person Edgars Pivovarenoks    schedule 02.06.2016

Я знаю, что все они действительны, но является ли лучший / приемлемый способ кодирования конструкторов?

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

Есть ли недостатки с именованными / необязательными параметрами, которые мне не хватает?

Насколько мне известно, нет. Лично я считаю, что это лучшее решение, но другие могут отличаться.

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

Добро пожаловать в программирование. Нас, программистов, миллионы, и мы все заняты усложнением мира!

person Alastair Brown    schedule 02.06.2016

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

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

В качестве альтернативы вы можете использовать частные конструкторы.

person Pablo H    schedule 30.12.2019