Конструктор в C# является членом класса. Это метод в классе, который выполняется при создании объекта класса. Обычно мы помещаем код инициализации в конструктор.
Имя конструктора всегда совпадает с именем класса. Конструктор в C# может быть открытым или закрытым. Класс может иметь несколько перегруженных конструкторов.
Написать конструктор в классе довольно просто, взгляните на следующий пример:
- public class mySampleClass
- {
- public mySampleClass()
- {
- // Это метод конструктора.
- }
- // Остальные члены класса идут сюда.
- }
Когда объект этого класса будет создан, этот конструктор будет выполнен. Что-то вроде этого:
- mySampleClass obj = new mySampleClass()
- // В это время код в конструкторе будет выполнен
Перегрузка конструктора
C# поддерживает перегрузку конструкторов, это означает, что у нас могут быть конструкторы с другим набором параметров.
Так что наш класс может быть таким:
- public class mySampleClass
- {
- public mySampleClass()
- {
- // Это метод конструктора без параметров.
- // Первый конструктор
- }
- public mySampleClass(int Age)
- {
- // Это конструктор с одним параметром.
- // Второй конструктор
- }
- public mySampleClass(int Age, string Name)
- {
- // Это конструктор с двумя параметрами.
- // Третий конструктор
- }
- // Остальные члены класса идут сюда.
- }
Обратите внимание, что вызов конструктора теперь зависит от того, как вы создаете объект. Например:
- mySampleClass obj = new mySampleClass()
- // На данный момент код без параметра
- // конструктор (Первый конструктор) будет выполнен
- mySampleClass obj = new mySampleClass(12)
- // В это время код одного параметра
- // конструктор (второй конструктор) будет
- // выполнен.
Обращение к конструкторам полностью регулируется здесь правилами перегрузки.
Вызов конструктора из другого конструктора
Вы всегда можете сделать вызов одного конструктора из другого. Скажем, например:
- public class mySampleClass
- {
- public mySampleClass(): this(10)
- {
- // Это метод конструктора без параметров.
- // Первый конструктор
- }
- public mySampleClass(int Age)
- {
- // Это конструктор с одним параметром.
- // Второй конструктор
- }
- }
Прежде всего, давайте посмотрим на синтаксис:
- public mySampleClass(): this(10)
Здесь это относится к тому же классу, поэтому когда мы говорим this(10), мы фактически имеем в виду выполнение открытого метода mySampleClass(int Age).
Вышеупомянутый способ вызова метода называется initializer. Таким образом, в методе может быть не более одного инициализатора.
Еще одна вещь, которую мы должны знать, это последовательность выполнения, т.е. Какой метод будет выполняться когда. Здесь, если я создаю объект как
- mySampleClass obj = new mySampleClass()
Тогда код public mySampleClass (int Age) будет выполнен перед кодом mySampleClass (). Итак, практически определение метода:
- public mySampleClass(): this(10)
- {
- // Это метод конструктора без параметров.
- // Первый конструктор
-
- }
эквивалентно:
- public mySampleClass()
- {
- mySampleClass(10);
- // Это метод конструктора без параметров.
- // Первый конструктор
- }
Обратите внимание, что в инициализаторах разрешены только ключевые слова this и base (мы увидим это далее), другие вызовы методов вызовут ошибку.
Это иногда называется конструкторской цепочкой .
Поведение Конструкторов в Наследовании
Давайте сначала создадим унаследованный класс.
- public class myBaseClass
- {
- public myBaseClass()
- {
- // Код для конструктора первого базового класса
- }
- public myBaseClass(int Age)
- {
- // Код для конструктора второго базового класса
- }
- // Остальные члены класса идут сюда.
- }
- public class myDerivedClass : myBaseClass
- // Обратите внимание, что я наследую класс здесь.
- {
- public myDerivedClass()
- {
- // Код для первого конструктора myDerivedClass.
- }
- public myDerivedClass(int Age):base(Age)
- {
- // Код для второго конструктора myDerivedClass.
- }
- // Остальные члены класса идут сюда.
- }
Теперь, какова будет последовательность выполнения здесь:
если я создам объект класса Derived как
- myDerivedClass obj = new myDerivedClass();
Тогда последовательность выполнения будет:
- Открытый метод myBaseClass().
- А затем публичный метод myDerivedClass().
Примечание. Если мы не предоставляем инициализатор, ссылающийся на конструктор базового класса, он выполняет конструктор без параметров базового класса.
Обратите внимание на одну вещь: мы не делаем никаких явных вызовов конструктору базового класса ни инициализатором, ни ключевым словом base (), но он все еще выполняется. Это нормальное поведение конструктора.
Если я создаю объект класса Derived как,
- myDerivedClass obj = new myDerivedClass(15);
Тогда последовательность выполнения будет:
- Публичный метод myBaseClass (int Age).
- А затем публичный метод myDerivedClass (int Age).
Здесь появилась новая база ключевых слов. Это относится к базовому классу текущего класса. Итак, здесь это относится к myBaseClass. И base (10) относится к вызову метода myBaseClass (int Age).
Также обратите внимание на использование переменной Age в синтаксисе:
- public myDerivedClass(int Age):base(Age)
Понимание этого оставлено читателю.
Статические Конструкторы
Это новая концепция, представленная в C#. Под новым здесь я подразумеваю, что он не был доступен для разработчиков C++.
Это специальный конструктор, который вызывается перед созданием первого объекта класса. Время выполнения не может быть определено, но оно определенно перед созданием первого объекта - может быть во время загрузки сборки.
Синтаксис написания статических конструкторов также прост:
- public class myClass
- {
- static myClass()
- {
- // Код инициализации идет сюда.
- // Здесь можно получить доступ только к статическим членам.
- }
- }
- // Другие методы класса идут сюда
- }
Примечания для статических конструкторов:
- В классе может быть только один статический конструктор.
- Статический конструктор должен быть без параметров.
- Он может получить доступ только к статическим членам класса.
- В определении статического конструктора не должно быть модификатора доступа.
Хорошо, все вышеперечисленные пункты в порядке, но почему это так? Давайте пойдем шаг за шагом здесь.
Во-первых, вызов статического метода выполняется CLR, а не объектом, поэтому нам не нужно иметь модификатор доступа к нему.
Во-вторых, он будет вызываться CLR, который может передать ему параметры, если требуется, никто, поэтому у нас не может быть параметризованного статического конструктора.
В-третьих, нестатические члены в классе специфичны для экземпляра объекта, поэтому статический конструктор, если ему разрешено работать с нестатическими членами, будет отражать изменения во всех экземплярах объекта, что нецелесообразно. Таким образом, статический конструктор может получить доступ только к статическим членам класса.
В-четвертых, перегрузка требует, чтобы два метода отличались в смысле определения методов, чего нельзя сделать со статическими конструкторами, поэтому вы можете иметь не более одного статического конструктора в классе.
Теперь возникает один вопрос, можем ли мы иметь два конструктора, как:
- public class myClass
- {
- static myClass()
- {
- // Код инициализации идет сюда.
- // Здесь можно получить доступ только к статическим членам.
- }
- public myClass()
- {
- // Код для первого конструктора myDerivedClass.
- }
- // Другие методы класса идут сюда
- }
Это совершенно верно, хотя, похоже, не соответствует концепциям перегрузки. Но почему? Потому что время выполнения двух методов различно. Один - во время загрузки сборки, а другой - во время создания объекта.