
10.3. Статические константы
Константы могут быть локализованы в теле метода, а могут принадлежать классу. В последнем случае они по умолчанию без модификатора static являются статическими, т.е. недоступны через ссылку на объекты класса.
Объявление статической константы имеет вид:
модификаторыopt const тип_константы
список_объявлений_констант
Необязательные модификаторы для констант - это при отсутствии наследования модификаторы доступа (public, private, protected, internal).
Объявление из списка_объявлений_констант имеет вид:
идентификатор=инициализирующее_выражение.
Идентификатор служит именем статической константы. В инициализирующее выражение имеют право входить только константы-литералы и статические константы. (Порядок их размещения в объявлении класса безразличен.) Каждая константа должна быть обязательно явно инициализирована. Умалчиваемые значения для статических констант не предусмотрены.
Пример с классом статических констант:
// 10_04.cs - статические константы класса
class Lekc10_04
{
class Constants
{
public const double скорость_света = 299793; // км/сек
public const double радиус_электрона = 2.82e-13; // см
}
public static void Main()
{
Console.WriteLine("радиус_электрона = {0}", Constants.радиус_электрона);
}
}
Результат выполнения программы: радиус_электрона = 2,82Е-13
В отличие от статических полей константы инициализируются однажды и не принимают до явной инициализации промежуточных умалчиваемых значений. Поэтому последовательность размещения объявлений статических констант не важна. Для иллюстрации этой особенности приведём следующую программу:
// 10_05.cs - статические константы разных классов
class Lekc10_05
{
class One
{
public const double circle = 2 * pi * Two.radius;
public const double pi = 3.14159;
}
class Two
{
public const double radius = 20;
}
public 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. Конечно, при инициализации нескольких констант недопустимо появление "зацикливания". В инициализатор константы К1 не должна входить константа К2, в инициализатор которой входит константа К1.
Указанное "зацикливание" никогда не возникает при инициализации статических полей (даже имеющих модификатор 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 - статические методы класса
class Lekc10_06
{
class newClass
{
static int n = 5;
static int x = fl(n);
public static int у = fb(n) ? 10 : -10;
public static int getX() { return x; }
static bool fb(int a) { return a % 2 == 0 ? true : false; }
static int fl(int d) { return d * d * d; }
}
public static void Main()
{
Console.WriteLine("newClass.у = " + newClass.у);
Console.WriteLine("newClass.getX() = " + newClass.getX());
}
}
Результат выполнения программы: newClass.у = -10
newClass.getX() = 125
Обратие внимание, что в классе newClass только два открытых члена -поле int у и метод getX(). Поля х, n и методы fb(), fl() недоступны вне класса.
В теле любого метода могут быть объявлены локальные переменные и константы с типами ссылок и значений. Имена таких переменных имеют право совпадать с именами статических членов того класса, в котором размещён метод. В этом случае локальная переменная "экранирует" одноимённую статическую переменную. То есть имя без квалификатора "имя_класса." при совпадении имён относится только к локальному объекту метода. В качестве примера рассмотрим следующий метод Main() из класса Test_cs:
// 10_07.cs - Статические поля класса и локальные данные методов
class Lekc10_07
{
public class Test_cs
{
public static int n = 10; // инициализация разрешена
public static string line = new string('*', n);
public static double constant = 9.81; // поле класса Test_cs
double pi = 3.14159; // поле объекта класса Test_cs
public 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(Test_cs.line);
Test_cs.n = 20; // изменили значение поля класса
Test_cs.line = new string('*', n); // изменили значение ссылки
Console.WriteLine(Test_cs.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) к его полям обращаться нельзя, их нет.
Каждое статическое поле существует только в единственном экземпляре. Статические поля класса играют роль глобальных переменных для всех методов, у которых есть право доступа к этому классу.
Итак, пока не создан объект класса, существуют и доступны только статические члены класса.