- •Классы и структуры
- •Функции-члены
- •Передача параметров в методы
- •Параметры ref
- •Параметры out
- •Свойства
- •Свойства, доступные только для чтения и только для записи
- •Модификаторы доступа для свойств
- •Автоматически реализуемые свойства
- •Замечание о встраивании
- •Индексаторы
- •Тип_элемента this[int индекс]
- •Листинг 1.
- •Листинг 2.
- •Листинг 3.
- •Листинг 4.
- •Конструкторы
- •Статические конструкторы
- •Вызов одних конструкторов из других
- •Поля readonly
- •Анонимные типы
- •Структуры
- •Структуры это типы значений
- •Структуры и наследование
- •Конструкторы структур
- •Частичные классы
- •Статические классы
- •Класс Object
- •Методы System.Object
- •Метод ToString()
- •Расширяющие методы
Статические конструкторы
Одним из новых средств С# является возможность написания статических конструкторов класса без параметров. Такой конструктор выполняется лишь однажды, в противоположность всем описанным до сих пор конструкторам, которые были конструкторами экземпляров и выполнялись при каждом создании объектов классов.
class MyClass
{
static MyClass ()
{
// код инициализации
}
// остаток определения класса
}
Одной из причин для написания статического конструктора может быть наличие в классе некоторых статических полей или свойств, которые должны быть инициализированы внешним источником, прежде чем класс будет использован впервые.
Исполняющая среда .NET не дает никаких гарантий того, что статический конструктор будет вызван, поэтому в него не следует помещать код, который должен быть выполнен в определенный момент (например, при загрузке сборки в память). Точно так же невозможно предсказать, в каком порядке будут выполнены статические конструкторы различных классов.
Единственное, что гарантируется это то, что статический конструктор будет запущен максимум один раз и что он будет вызван до любого первого обращения к данному классу. В С# статический конструктор обычно выполняется непосредственно перед первым вызовом любого члена класса.
Обратите внимание, что статический конструктор не имеет никакого модификатора доступа. Он никогда не вызывается никаким другим кодом С#, а всегда только исполняющей средой .NET при загрузке класса, поэтому никакой модификатор доступа вроде public или private не имеет смысла. По той же причине статический конструктор не может принимать никаких параметров, и у каждого класса может быть только один статический конструктор. Должно быть очевидным также, что статический конструктор может иметь доступ только к статическим членам класса, но не членам экземпляра.
Также следует отметить, что в классе допускается определять одновременно статический конструктор и конструктор экземпляра без параметров. Хотя их списки параметров идентичны, не возникает никакого конфликта, потому что статический конструктор выполняется во время загрузки класса, а конструктор экземпляра при создании экземпляра, поэтому не происходит никакой путаницы с тем, когда какой конструктор вызывать.
Кроме того, если есть более одного класса со статическим конструктором, то неизвестно, какой из статических конструкторов будет вызван первым. Поэтому в статический конструктор не должен помещаться код, который бы зависел от того, были или не были вызваны ранее другие статические конструкторы. С другой стороны, если любые статические поля должны иметь определенные значения по умолчанию, то они будут размещены, до вызова статического конструктора.
Следующий пример иллюстрирует применение статического конструктора и основан на идее программы, имеющей некоторые пользовательские предпочтения (которые предварительно сохранены в конфигурационном файле). Для простоты предположим, что имеется только одно пользовательское предпочтение значение BackColor, которое может представлять цвет фона, используемый приложением. И поскольку мы здесь не хотим погружаться в детали написания кода, читающего данные из внешнего источника, то предположим, что предпочтительный цвет фона красный по будним дням и зеленый по выходным. Все, что должна делать программа это отображать предпочтение в консольном окне. Этого будет достаточно, чтобы увидеть работу статического конструктора.
namespace Wrox.ProCSharp.StaticConstructorSample
{
public class UserPreferences
{
public static readonly Color BackColor;
static UserPreferences ()
{
DateTime now = DateTime.Now;
if (now.DayOfWeek == DayOfWeek.Saturday ||
now.DayOfWeek == DayOfWeek.Sunday)
BackColor = Color.Green;
else
BackColor = Color.Red;
}
private UserPreferences ()
{
}
}
}
Приведенный код демонстрирует, как предпочтительный цвет сохраняется в статической переменной, которая инициализируется статическим конструктором. Это поле объявлено как доступное только для чтения, т.е. его значение может быть установлено только в конструкторе. Далее в этой главе вы узнаете подробнее о полях, доступных только для чтения. Код использует ряд удобных структур, которые поставляются Microsoft как часть библиотеки классов .NET System.DateTime и System.Drawing.Color.DateTime.
В Color.DateTime реализовано статическое свойство Now, возвращающее текущее время, и свойство экземпляра DayOfWeek, которое определяет, на какой день недели приходится дата и время. Структура Color применяется для хранения цветов. Здесь реализованы также различные статические свойства, наподобие Red и Green, которые, как показано в этом примере, возвращают часто используемые цвета. Чтобы использовать Color, во время компиляции необходимо сослаться на сборку System.Drawing.dll и добавить оператор using для пространства имен System.Drawing:
using System;
using System.Drawing;
Статический конструктор можно протестировать с помощью следующего кода:
class MainEntryPoint
{
static void Main(string[] args)
{
Console.WriteLine("Предпочтение пользователя: BackColor равно: "
+ UserPreferences.BackColor.ToString());
}
}
Компиляция и запуск этого кода даст следующий вывод:
Предпочтение пользователя: BackColor равно: Color [Red]
Конечно, если код выполняется в конце недели, предпочитаемым цветом может быть Green.