Цепочка конструкторов 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
}
}