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

CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky

.pdf
Скачиваний:
31
Добавлен:
22.03.2016
Размер:
2.08 Mб
Скачать

=выражение

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

=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