Цепочка конструкторов C#? (Как это сделать?)

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

Я был бы признателен некоторые примеры с объяснением.

Так как же их приковать? Я знай с двумя идет:

public SomeClass this: {0}

public SomeClass
{
    someVariable = 0
} 

а как ты справляешься с тремя, четырьмя и так далее?

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

8 ответов


вы используете стандартный синтаксис (используя this как метод), чтобы выбрать перегрузку,внутри класс:

class Foo {
    private int id;
    private string name;
    public Foo() : this(0, "") {
    }
    public Foo(int id, string name) {
        this.id = id;
        this.name = name;
    }
    public Foo(int id) : this(id, "") {
    }
    public Foo(string name) : this(0, name) {
    }
}

затем:

Foo a = new Foo(), b = new Foo(456,"def"), c = new Foo(123), d = new Foo("abc");

дополнительные услуги:

  • вы можете привязать к конструкторам базового типа с помощью base(...)
  • вы можете поместить дополнительный код в каждом конструкторе
  • значение по умолчанию (если вы ничего не указываете) -base()

"почему?":

  • код сокращение (всегда хорошо)
  • необходимые для вызова нестандартного базового конструктора, например:

    SomeBaseType(int id) : base(id) {...}
    

обратите внимание, что вы также можете использовать инициализаторы объектов аналогичным образом (без необходимости писать что-либо):

SomeType x = new SomeType(), y = new SomeType { Key = "abc" },
         z = new SomeType { DoB = DateTime.Today };

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

однако, если вы останавливаетесь в 4.0, у меня есть хорошие новости. Теперь вы можете иметь один конструктор с необязательными аргументами! Я упрощу пример класса Foo:

class Foo {
  private int id;
  private string name;

  public Foo(int id = 0, string name = "") {
    this.id = id;
    this.name = name;
  }
}

class Main() {
  // Foo Int:
  Foo myFooOne = new Foo(12);
  // Foo String:
  Foo myFooTwo = new Foo(name:"Timothy");
  // Foo Both:
  Foo myFooThree = new Foo(13, name:"Monkey");
}

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

Я надеюсь, вам понравился этот урок! Я просто не могу поверить, что разработчики жалуются на построение цепочки и не могут использовать необязательные аргументы по умолчанию с 2004/2005! Теперь это заняло так много времени в мире разработки, что разработчики боятся использовать его, потому что он не будет обратно совместим.


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

public Person(string name) : this(name, string.Empty)
{
}

public Person(string name, string address) : this(name, address, string.Empty)
{
}

public Person(string name, string address, string postcode)
{
    this.Name = name;
    this.Address = address;
    this.Postcode = postcode;
}

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

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


У меня есть класс дневника, и поэтому я не пишу установку значений снова и снова

public Diary() {
    this.Like = defaultLike;
    this.Dislike = defaultDislike;
}

public Diary(string title, string diary): this()
{
    this.Title = title;
    this.DiaryText = diary;
}

public Diary(string title, string diary, string category): this(title, diary) {
    this.Category = category;
}

public Diary(int id, string title, string diary, string category)
    : this(title, diary, category)
{
    this.DiaryID = id;
}

что такое использование "цепочки конструкторов"?
Вы используете его для вызова одного конструктора из другого конструктора.

как реализовать "цепочку конструкторов"?
Используйте ключевое слово": this (yourProperties) " после определения конструктора. например:

Class MyBillClass
{
    private DateTime requestDate;
    private int requestCount;

    public MyBillClass()
    {
        /// ===== we naming "a" constructor ===== ///
        requestDate = DateTime.Now;
    }
    public MyBillClass(int inputCount) : this()
    {
        /// ===== we naming "b" constructor ===== ///
        /// ===== This method is "Chained Method" ===== ///
        this.requestCount= inputCount;
    }
}

почему это полезно?
Важной причиной является сокращение кодирования и предотвращение дублирования кода. например, повторяющийся код для инициализации свойства Предполагать некоторое свойство в классе должно быть инициализировано определенным значением (в нашем примере requestDate). И класс имеет 2 или более конструктора. Без "цепь конструктор", необходимо повторить код initializaion во всех constractorsбыл класса.

как это работает? (Или, что такое последовательность выполнения в "цепочке конструкторов")?
в приведенном выше примере сначала будет выполнен метод "a", а затем последовательность команд вернется к методу"b". Другими словами, приведенный выше код равен ниже:

Class MyBillClass
{
    private DateTime requestDate;
    private int requestCount;

    public MyBillClass()
    {
        /// ===== we naming "a" constructor ===== ///
        requestDate = DateTime.Now;
    }
    public MyBillClass(int inputCount) : this()
    {
        /// ===== we naming "b" constructor ===== ///
        // ===== This method is "Chained Method" ===== ///

        /// *** --- > Compiler execute "MyBillClass()" first, And then continue instruction sequence from here
        this.requestCount= inputCount;
    }
}

вы спрашиваете об этом?

  public class VariantDate {
    public int day;
    public int month;
    public int year;

    public VariantDate(int day) : this(day, 1) {}

    public VariantDate(int day, int month) : this(day, month,1900){}

    public VariantDate(int day, int month, int year){
    this.day=day;
    this.month=month;
    this.year=year;
    }

}

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

Кстати, я использовал LINQPad для этого примера, если вам интересно, что *.Dump() is.
ура

void Main()
{

    CtorChaining ctorNoparam = new CtorChaining();
    ctorNoparam.Dump();
    //Result --> BaseDir C:\Program Files (x86)\Default\ 

    CtorChaining ctorOneparam = new CtorChaining("c:\customDir");
    ctorOneparam.Dump();    
    //Result --> BaseDir c:\customDir 
}

public class CtorChaining
{
    public string BaseDir;
    public static string DefaultDir = @"C:\Program Files (x86)\Default\";


    public CtorChaining(): this(null) {}

    public CtorChaining(string baseDir): this(baseDir, DefaultDir){}

    public CtorChaining(string baseDir, string defaultDir)
    {
        //if baseDir == null, this.BaseDir = @"C:\Program Files (x86)\Default\"
        this.BaseDir = baseDir ?? defaultDir;
    }
}

в цепочке конструкторов есть еще один важный момент: порядок. Почему? Предположим, что объект создается во время выполнения платформой, которая ожидает, что это конструктор по умолчанию. Если вы хотите быть в состоянии пройти в значениях, имея возможность пройти в argments конструктор, если вы хотите, это очень полезно.

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

public class MyClass
{
  private IDependency _myDependency;
  MyClass(){ _myDependency = new DefaultDependency(); }
  MYClass(IMyDependency dependency) : this() {
    _myDependency = dependency; //now our dependency object replaces the defaultDependency
  }
}