Подтвердить что ты не робот

С# конструктор цепочки? (Как это сделать?)

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

Я хотел бы получить несколько примеров с объяснением.

Так как же их цепочки? Я знаю, что с двумя идет:

public SomeClass this: {0}

public SomeClass
{
    someVariable = 0
} 

Но как вы это делаете с тремя, четырьмя и так далее?

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

4b9b3361

Ответ 1

Вы используете стандартный синтаксис (используя 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 };

Ответ 2

Я просто хочу поднять действительный момент для всех, кто ищет это. Если вы собираетесь работать с версиями .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! Теперь он занял много времени в мире разработки, что разработчики боятся использовать его, потому что он не будет обратно совместим.

Ответ 3

Это лучше всего иллюстрируется примером. Imaging у нас есть класс Person

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.Empty through к имени и адресу, который затем отправляет значение по умолчанию для почтового индекса через конечный конструктор.

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

Ответ 4

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

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

Ответ 5

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

Как реализовать "цепочку конструкторов"?
Используйте ключевое слово ": 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 или более конструктора. Без "Constructor Chain" вы должны повторить код инициализации во всех создателях класса.

Как это работает? (Или, что такое последовательность выполнения в "Цепочке конструктора" )?
в приведенном выше примере сначала будет выполняться метод "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;
    }
}

Ответ 6

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

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

}

Ответ 7

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

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

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

Ответ 8

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

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

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