0Pricing
C# Academy · Урок

Цепочка конструкторов с this

Повторно используйте инициализацию в разных конструкторах.

«Цепочка конструкторов с this» — бесплатный урок C# Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Зачем объединять конструкторы в цепочку

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

using System;

class Box
{
    public int Width;
    public int Height;

    public Box(int width, int height)
    {
        Width = width;
        Height = height;
    }

    public Box() : this(1, 1) { }
}

class Program
{
    static void Main()
    {
        var def = new Box();
        Console.WriteLine(def.Width + "x" + def.Height);
    }
}

Синтаксис : this(...)

Цепочка задаётся с помощью : this(args) после сигнатуры конструктора. Целевой конструктор выполняется сначала, затем выполняется текущее тело.

using System;

class Person
{
    public string Name;
    public int Age;

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
        Console.WriteLine("Full constructor ran");
    }

    public Person(string name) : this(name, 0)
    {
        Console.WriteLine("Name-only constructor ran");
    }
}

class Program
{
    static void Main()
    {
        var p = new Person("Sam");
        Console.WriteLine(p.Name + ", " + p.Age);
    }
}

Порядок выполнения

Цепочный конструктор выполняется до тела вызывающего конструктора. Это гарантирует, что базовая инициализация произойдёт первой.

using System;

class Step
{
    public Step(int n)
    {
        Console.WriteLine("Init with " + n);
    }

    public Step() : this(0)
    {
        Console.WriteLine("Then default body");
    }
}

class Program
{
    static void Main()
    {
        var s = new Step();
    }
}

Единый источник истины

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

using System;

class Connection
{
    public string Host;
    public int Port;

    public Connection(string host, int port)
    {
        Host = host;
        Port = port;
    }

    public Connection(string host) : this(host, 8080) { }
    public Connection() : this("localhost", 8080) { }
}

class Program
{
    static void Main()
    {
        var c = new Connection("example.com");
        Console.WriteLine(c.Host + ":" + c.Port);
    }
}

Цепочка со значениями по умолчанию

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

using System;

class Coffee
{
    public string Size;
    public bool Milk;
    public int Sugar;

    public Coffee(string size, bool milk, int sugar)
    {
        Size = size;
        Milk = milk;
        Sugar = sugar;
    }

    public Coffee(string size, bool milk) : this(size, milk, 0) { }
    public Coffee(string size) : this(size, false) { }
}

class Program
{
    static void Main()
    {
        var c = new Coffee("large");
        Console.WriteLine(c.Size + ", milk=" + c.Milk + ", sugar=" + c.Sugar);
    }
}

Проверка в целевом конструкторе

Поскольку каждый конструктор проходит через основной, проверка, написанная в нём, защищает все пути создания объекта.

using System;

class Rect
{
    public int W;
    public int H;

    public Rect(int w, int h)
    {
        if (w <= 0 || h <= 0)
            throw new ArgumentException("Dimensions must be positive");
        W = w;
        H = h;
    }

    public Rect(int side) : this(side, side) { }
}

class Program
{
    static void Main()
    {
        var square = new Rect(5);
        Console.WriteLine(square.W + "x" + square.H);
    }
}

Цепочка и параметры по умолчанию

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

using System;

class Logger
{
    public string Prefix;
    public bool Verbose;

    public Logger(string prefix, bool verbose)
    {
        Prefix = prefix;
        Verbose = verbose;
    }

    public Logger(string prefix) : this(prefix, false)
    {
        Console.WriteLine("Created quiet logger");
    }
}

class Program
{
    static void Main()
    {
        var log = new Logger("APP");
        Console.WriteLine(log.Prefix + " verbose=" + log.Verbose);
    }
}

Пустые тела — обычное явление

У конструктора в цепочке часто бывает пустое тело { }, потому что вся работа выполняется в целевом конструкторе.

using System;

class Vector
{
    public double X, Y, Z;

    public Vector(double x, double y, double z)
    {
        X = x; Y = y; Z = z;
    }

    public Vector(double v) : this(v, v, v) { }
}

class Program
{
    static void Main()
    {
        var v = new Vector(2);
        Console.WriteLine(v.X + "," + v.Y + "," + v.Z);
    }
}

Как избежать циклов

Конструкторы не должны вызывать друг друга по кругу (A вызывает B, B вызывает A). Компилятор отклоняет циклические цепочки : this(...).

using System;

class Safe
{
    public int A, B;

    public Safe(int a, int b)
    {
        A = a;
        B = b;
    }

    public Safe(int a) : this(a, 0) { }   // chains one direction only
}

class Program
{
    static void Main()
    {
        var s = new Safe(7);
        Console.WriteLine(s.A + ", " + s.B);
    }
}

Сочетание с this.field

Вы можете использовать цепочку и при этом обращаться к this. в теле для дополнительной настройки после возврата из целевого конструктора.

using System;

class Account
{
    public string Owner;
    public decimal Balance;
    public bool Active;

    public Account(string owner, decimal balance)
    {
        this.Owner = owner;
        this.Balance = balance;
    }

    public Account(string owner) : this(owner, 0m)
    {
        this.Active = true;
    }
}

class Program
{
    static void Main()
    {
        var a = new Account("Rin");
        Console.WriteLine(a.Owner + " active=" + a.Active);
    }
}

Объединение всего вместе

Цепочка помогает сделать класс соответствующим принципу DRY: один конструктор выполняет проверку и присваивание, а остальные предоставляют удобные сокращённые варианты.

using System;

class Pizza
{
    public string Size;
    public int Toppings;

    public Pizza(string size, int toppings)
    {
        if (toppings < 0) throw new ArgumentException("toppings");
        Size = size;
        Toppings = toppings;
    }

    public Pizza(string size) : this(size, 0) { }
    public Pizza() : this("medium") { }
}

class Program
{
    static void Main()
    {
        var p = new Pizza();
        Console.WriteLine(p.Size + " with " + p.Toppings + " toppings");
    }
}

Быстрая проверка

Проверьте, насколько хорошо Вы поняли цепочку конструкторов.

Итоги

Цепочка конструкторов использует : this(args), чтобы вызвать другой конструктор того же класса. Целевой конструктор выполняется первым, затем выполняется текущее тело. Направляйте каждый конструктор через один основной, чтобы централизовать проверку и избежать дублирования инициализации. Циклические цепочки не допускаются.

using System;

class Demo
{
    public int X, Y;
    public Demo(int x, int y) { X = x; Y = y; }
    public Demo(int both) : this(both, both) { }
}

class Program
{
    static void Main()
    {
        var d = new Demo(4);
        Console.WriteLine(d.X + "," + d.Y);
    }
}

Часто задаваемые вопросы

Урок «Цепочка конструкторов с this» бесплатный?

Да — полный текст урока «Цепочка конструкторов с this» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Цепочка конструкторов с this»?

Повторно используйте инициализацию в разных конструкторах. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Цепочка конструкторов с this»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Определение конструкторов
  2. Цепочка конструкторов с this
  3. Инициализаторы объектов и коллекций
  4. Статические конструкторы
← Назад к C# Academy