Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky

.pdf
Скачиваний:
36
Добавлен:
22.03.2016
Размер:
2 Мб
Скачать
☆

=выражение

=инициализатор_массива

=new тип (аргументы_конструктора)

Ввыражение инициализатора, в инициализатор массива и в выражения,

используемые в качестве аргументов конструктора, могут входить константы–

литералы, а также другие статические члены этого класса.

Нестатические члены невозможно использовать в инициализирующем

выражении статического поля.

Пример инициализации и использования статических полей:

// 10_01.cs - статические поля класса using System;

class T {

int x; // поле объектов класса

static int y = 3; // y = x + 5; - ошибка: х – поле объекта public static int z = 5 - y; // эквивалент: z = 5 - T.y;

}

class Program

{

static void Main()

{

// Console.WriteLine("T.y = " + T.y); // Error! T.y is private! int z = T.z; // z и T.z - разные переменные! Console.WriteLine("T.z = " + ++T.z); // изменяется T.z Console.WriteLine("z = {0}", z);

}

}

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

T.z = 3 z = 2

Следует отметить одну особенность инициализации статических полей

"поле:инициализация статических полей" . Вначе они все получают умалчиваемые значения (для арифметических типов – нулевые). Затем последовательно (сверху вниз) выполняются инициализаторы. Тем самым, если в инициализирующее выражение входит в качестве операнда статическое поле, которое ещё не инициализировано явно, то для него берётся умалчиваемое (например, нулевое)

значение. В качестве примера рассмотрим программу:

// 10_02.cs - статические поля - порядок инициализации using System;

class T

{

public static int x = y; static int y = 3; public static int z = y;

}

class Program

{

static void Main()

{

Console.WriteLine("T.x = " + T.x);

Console.WriteLine("T.z = " + T.z);

}

}

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

T.x = 0

T.z = 3

Обратите внимание, что поле y по умолчанию закрытое (имеет статус доступа private) и обращение к нему невозможно вне класса T.

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

выражениях разных классов.

// 10_03.cs - статические поля разных классов using System;

class c1 {

public static double orbit = 2 * c2.pi * c3.radius;

}

class c2 {

public static double pi = double.Parse(c3.str);

}

class c3 {

public static string str = "3,14159"; public static double radius = 10;

}

class Program

{

static void Main()

{

Console.WriteLine("c1.orbit = {0}", c1.orbit); c3.radius = 20;

Console.WriteLine("c3.radius = {0}", c3.radius); Console.WriteLine("c1.orbit = {0}", c1.orbit);

}

}

Результат выполнения программы: c1.orbit = 62,8318

c3.radius = 20 c1.orbit = 62,8318

Инициализация статических полей "поле:инициализация статических полей"

выполняется только однажды. Поэтому значение поля c1.orbit не изменилось после изменения c3.radius в методе Main( ).

10.3. Статические константы

Константы "константы" могут быть локализованы в теле метода, а могут принадлежать классу. В последнем случае они по умолчанию без модификатора static являются статическими, т.е. недоступны через ссылку на объекты класса.

Объявление статической константы "константы:объявление статической

константы" имеет вид:

модификаторыopt const тип_константы список_объявлений_констант

Необязательные модификаторы для констант – это при отсутствии

наследования модификаторы доступа (public, private, protected, internal).

Объявление из списка_объявлений_констант имеет вид:

идентификатор=инициализирующее_выражение.

Идентификатор служит именем статической константы. В

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

Умалчиваемые значения для статических констант не предусмотрены. Пример с классом статических констант:

// 10_04.cs - статические константы класса using System;

class Constants

{

public const double скорость_света = 299793; // км/сек public const double радиус_электрона = 2.82e-13; // см

}

class Program

{

static void Main()

{

Console.WriteLine("радиус_электрона = {0}", Constants.радиус_электрона); }

}

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

радиус_электрона = 2,82E-13

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

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

важна. Для иллюстрации этой особенности приведём следующую программу:

// 10_05.cs - статические константы разных классов using System;

class One {

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

}

class Two

{

public const double radius = 20;

}

class Program

{

static void Main()

{

Console.WriteLine("One.circle = {0}", One.circle);

}

}

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

One.circle = 125,6636

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

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

"рациональной" последовательности, независимо от порядка размещения

объявлений. Эти особенности иллюстрируют объявления констант в классе 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(). В этом случае для обращения к методу можно использовать выражение имя_метода(список_аргументов). Если статический метод определён в другом классе, то для обращения к нему используется выражение вида:

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

По умолчанию статический метод имеет модификатор доступа 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());

}

}

Результат выполнения программы: 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; // локальная константа 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) перед первым обращением к любому статическому полю класса или перед первым созданием экземпляра класса.

Конструкторы классов "конструктор:конструкторы классов" – статические и

нестатические (последние рассмотрены в главе 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; } static int n = 2;

static void Main()

{

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

}

}

Результат выполнения программы: numb=10, n = 22

В классе определены статические поля: ссылка ar, связанная с целочисленным массивом из 4-х элементов; целочисленные переменные numb и n. В теле статического конструктора переменным numb и n присваиваются значения,

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

Инициализация статических полей "поле:инициализация статических полей"

выполняется последовательно (сверху - вниз) по тексту определения класса. Поля,

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

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

Как рекомендует Стандарт C# [2], классы, которые не предназначены для создания объектов и которые содержат только статические члены, нужно

Соседние файлы в папке CSBasicCourse2ndedPodbelsky