Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Podbelsky_V_V_C_Bazovy_kurs.pdf
Скачиваний:
83
Добавлен:
02.06.2015
Размер:
1.73 Mб
Скачать

182

Г л а в а 1 0

 

 

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

public const double circle = 2*pi*Two.radius; public const double pi=3.14159;

В инициализатор константы circle входит константа pi, объявление которой следует за объявлением circle. Несмотря на это, значением circle будет 125,6636. Конечно, при инициализации нескольких констант недопустимо появление “зацикливания”. В инициализатор константы K1 не должна входить константа K2, в инициализатор которой входит константа K1.

Указанное “зацикливание” никогда не возникает при инициализации статических полей (даже имеющих модификатор readonly). Поле F2, объявление которого размещено ниже, может входить в инициализатор поля F1 – оно имеет там умалчиваемое значение. При этом поле F1, использованное в инициализатор F2, будет иметь там уже конкретное значение. Замена const на static readonly в предыдущем примере:

public static readonly double circle = 2*pi*Two.radius; public static readonly double pi=3.14159;

При такой инициализации значение circle будет 0.

10.4. Статические методы

Статический метод Main() мы уже используем, начиная с первой программы этой книги. Нам уже известно, что в теле метода Main() можно обращаться ко всем статическим членам того класса, где размещен метод Main().

Статические методы, отличные от Main(), мы уже подробно рассматривали, но ограничивались их размещением в том классе, где находится метод Main(). В этом случае для обращения к методу можно использовать выражение имя_метода(список_аргументов). Если статический метод определен в другом классе, то для обращения к нему используется выражение вида:

Класс как совокупность статических членов

183

 

 

По умолчанию статический метод имеет модификатор доступа private, т.е метод доступен только внутри класса. В объявлении статического метода, который планируется вызывать вне класса, необходимо указать модификатор доступа. В зависимости от дальнейшего применения метода используются модификаторы public (открытый), protected – (защищенный), internal

– (внутренний), protected internal – (защищённый внутренний). Области видимости, которые обеспечены перечисленными модификаторами, те же, что и для полей классов.

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

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

// 10_06.cs статические методы класса using System;

class newClass

{

static int n = 5; static int x = f1(n);

public static int y = fb(n) ? 10 : -10; public static int getX() { return x; }

static bool fb(int a) { return a % 2 == 0 ? true : false; } static int f1(int d) { return d * d * d; }

}

class Program

{

static void Main()

{

Console.WriteLine("newClass.y = " + newClass.y); Console.WriteLine("newClass.getX() = " + newClass.

getX());

}

имя_класса.имя_метода(список_аргументов)

}

 

184

Г л а в а 1 0

 

 

Результат выполнения программы:

newClass.y = -10 newClass.getX() = 125

Обратите внимание, что в классе newClass только два открытых члена – поле int y и метод getX(). Поля x, n и методы fb(), f1() недоступны вне класса.

В теле любого метода могут быть объявлены локальные переменные и константы с типами ссылок и значений. Имена таких переменных имеют право совпадать с именами статических членов того класса, в котором размещен метод. В этом случае локальная переменная “экранирует” одноименную статическую переменную, т. е. имя без квалификатора “имя_класса» при совпадении имён относится только к локальному объекту метода. В качестве примера рассмотрим следующий метод Main() из класса Test_cs:

// 10_07.cs Статические поля класса и локальные

данные методов using System; class Test_cs {

static int n = 10; // Инициализация разрешена static string line = new string('*', n);

static double constant = 9.81; // Поле класса Test_cs double pi = 3.14159; // Поле объекта класса Test_cs

static void Main() {

const double PI = 3.14159; // Локальная константа double circle; // Локальная переменная

//circle = 2 * pi * n; // Ошибка - нет объекта класса Test_ cs

circle = 2 * PI * n;

Console.WriteLine("Длина окружности=" + circle. ToString());

Console.WriteLine(line);

Test_cs.n = 20; // Изменили значение поля класса line = new string('*', n); // Изменили значение

ссылки

Console.WriteLine(line);

const double constant = 2.718282; // Локальная константа

Класс как совокупность статических членов

185

 

 

Console.WriteLine("Test_cs.constant=" + Test_ cs.constant);

Console.WriteLine("constant=" + constant);

}

}

Результат выполнения программы:

Длина окружности=62,8318

**********

********************

Test_cs.constant=9,81 constant=2,718282

В тексте метода Main():

PI – локальная именованная константа; circle – локальная переменная;

n, Test_cs.n – два обращения к одному и тому же статическому полю класса;

line – статическая ссылка–поле класса;

constant – локальная константа, имя которой совпадает с именем статического поля класса Test_cs.

Попытка обращения в теле метода Main() к нестатическому полю pi приводит к ошибке – пока не создан объект класса (объект, которому будет принадлежать поле pi), к его нестатическим полям обращаться нельзя, их нет.

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

Итак, пока не создан объект класса, существуют и доступны только статические члены класса.

10.5. Статический конструктор

Назначение статического конструктора - инициализация статических полей класса. Статический конструктор вызывается средой исполнения приложений (CLR) перед первым обращением к любому статическому полю класса или перед первым созданием экземпляра класса.

186

Г л а в а 1 0

 

 

Конструкторы классов – статические и нестатические (последние рассмотрены в главе 11) – обладают рядом особенностей, отличающих их от других методов классов. Имя конструктора всегда совпадает с именем того класса, которому он принадлежит. Для конструктора не указывается тип возвращаемого значения (даже тип void для конструктора запрещен). В теле конструктора нет необходимости, но допустимо, использовать оператор return. Для статического конструктора нельзя использовать модификаторы доступа.

Класс может иметь только один статический конструктор. Для статического конструктора параметры не указываются – спецификация параметров должна быть пустой.

Формат объявления статического конструктора:

static имя_класса( ) {операторы_тела_конструктора}

Статический конструктор невозможно вызвать непосредственно из программы – он вызывается только автоматически. Следует обратить внимание на то, что статический конструктор вызывается после выполнения инициализаторов статических полей класса. Основное назначение статического конструктора – выполнять более сложные действия, чем инициализаторы полей и констант. Для статического конструктора недоступны нестатические члены класса.

В качестве примера определим статический конструктор того класса, в котором размещён метод Main(). В том же классе определим несколько статических полей и выполним их инициализацию как с помощью инициализаторов, так и с применением статического конструктора.

// 10_08.cs Инициализаторы и статический

конструктор using System; class Program

{

static int[] ar = new int[] { 10, 20, 30, 40 }; static int numb = n + ar[3] - ar[1];

// Статический конструктор: static Program ()

{ numb /= n; n = ar[1] + n; }

Класс как совокупность статических членов

187

 

 

static int n = 2; static void Main()

{

Console.WriteLine("numb={0}, n = {1}", numb, n);

}

}

Результат выполнения программы:

numb=10, n = 22

Вклассе определены статические поля: ссылка ar, связанная

сцелочисленным массивом из четырех элементов; целочисленные переменные numb и n. В теле статического конструктора переменным numb и n присваиваются значения, отличные от тех, которые они получили при инициализации. Текст программы и результаты ее выполнения иллюстрируют следующие правила, большинство из которых мы уже приводили.

Инициализация статических полей выполняется последовательно (сверху - вниз) по тексту определения класса. Поля, для которых инициализация еще не выполнена, имеют умалчиваемые значения. (Для арифметических типов умалчиваемое значение статического поля равно нулю.) В инициализирующих выражениях статических полей допустимо использовать обращения к другим статическим членам классов. После выполнения инициализации статических полей выполняется статический конструктор, действия которого могут изменить значения статических полей.

10.6. Статические классы

Как рекомендует Стандарт C# [2], классы, которые не предназначены для создания объектов и которые содержат только статические члены, нужно объявлять статическими. В .NET Framework такими классами являются System.Control и System. Environment. Перечислим основные особенности статических классов.

В статических классах нет конструкторов экземпляров (объектов), и эти классы не могут служить базовыми классами при наследовании. (Наследование рассматривается

188

Г л а в а 1 0

 

 

в главе 13.) Статические классы могут использоваться только с операцией typeof и средствами доступа к членам класса. В частности, статический класс не может использоваться в качестве типа переменной и не может выступать в качестве типа параметра.

Взаголовок объявления статического класса входит модификатор static. В отличие от других классов статический класс нельзя объявить с модификаторами sealed и abstract. Однако, так как статический класс не участвует в иерархиях наследования, именно свойства классов с этими модификаторами присущи статическому классу.

Вобъявлении статического класса нельзя применять спецификатор базы. Кроме того, статический класс не может реализовывать интерфейсы. (Интерфейсам посвящена глава 14.) Статический класс имеет только один базовый класс System. Object.

Так как статический класс не может быть базовым, то для его членов запрещены модификаторы protected и protected internal. Для членов статического класса в качестве модификаторов доступа можно использовать только public и private.

Несмотря на наличие модификатора static в заголовке статического класса, все его члены, отличные от констант и вложенных типов (классов), должны быть объявлены с явно указанным модификатором static.

Статические классы удобно применять для логического объединения функционально близких методов.

Примеры статических классов приводить нет необходимости, так как многие классы этой главы включают только статические члены и каждый из этих классов может быть снабжен заголовком

static class имя_класса

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

Класс как совокупность статических членов

189

 

 

Контрольные вопросы

1.Перечислите члены класса, которые могут быть объявлены статическими.

2.Какие члены класса являются статическими без применения модификатора static?

3.Назовите модификаторы доступа.

4.Можно ли в объявлении члена класса использовать два модификатора доступа?

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

6.Что такое поле класса?

7.Когда (на каком этапе обработки программы) статическое поле размещается в памяти?

8.Можно ли в объявлении статического поля использовать модификатор доступа?

9.Что такое список объявлений поля?

10.Назовите формы инициализаторов полей.

11.Что разрешено использовать в инициализирующем выражении статического поля?

12.Как выполняется инициализация статических полей при отсутствии инициализаторов?

13.Объясните последовательность инициализации статических полей.

14.Какой статус доступа у статического поля при отсутствии модификатора доступа?

15.Как объявляются константы, принадлежащие классу?

16.Сформулируйте правила инициализации констант класса.

17.В чем отличие статических констант от статических полей с модификатором readonly?

18.Перечислите возможные применения и ограничения статических методов.

19.Что такое статический конструктор?

20.Сколько статических конструкторов в классе?

21.Какова спецификация параметров статического конструктора?

22.Как и когда вызывается статический конструктор?

23.Какие члены объявления класса доступны в теле статического конструктора?

24.Перечислите особенности статических классов.

25.Какие модификаторы не могут входить в объявление статического класса?

26.Какие модификаторы могут входить в объявления членов статического класса?

27.Может ли в статический класс входить нестатический рекурсивный метод?

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]