Выбрать главу

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

Откладывать инициализацию не стоит, как показывает пример с переменной s, объявленной с отложенной инициализацией. В вычислениях она дважды получает значение: один раз в операторе if, другой — в операторе цикла for. Тем не менее, при компиляции возникнет ошибка, утверждающая, что в процедуре WriteLine делается попытка использовать неинициализированную переменную s. Связано это с тем, что для операторов if и for на этапе компиляции не вычисляются условия, зависящие от переменных. Поэтому компилятор предполагает худшее — условия ложны, инициализация s в этих операторах не происходит. А за инициализацией наш компилятор следит строго, ты так и знай!

Время жизни и область видимости переменных

Давайте рассмотрим такие важные характеристики переменных, как время их жизни и область видимости. Зададимся вопросом, как долго живут объявленные переменные и в какой области программы видимы их имена? Ответ зависит от того, где и как, в каком контексте объявлены переменные. В языке C# не так уж много возможностей для объявления переменных, пожалуй, меньше, чем в любом другом языке. Открою "страшную" тайну, — здесь вообще нет настоящих глобальных переменных. Их отсутствие не следует считать некоторым недостатком С#, это достоинство языка. Но обо всем по порядку.

Поля

Первая важнейшая роль переменных, — они задают свойства структур, интерфейсов, классов. В языке C# такие переменные называются полями (fields). Структуры, интерфейсы, классы, поля — рассмотрению этих понятий будет посвящена большая часть этой книги, а сейчас сообщу лишь некоторые минимальные сведения, связанные с рассматриваемой темой. Поля объявляются при описании класса (и его частных случаев — интерфейса, структуры). Когда конструктор класса создает очередной объект — экземпляр класса, то он в динамической памяти создает набор полей, определяемых классом, и записывает в них значения, характеризующие свойства данного конкретного экземпляра.

Так что каждый объект в памяти можно рассматривать как набор соответствующих полей класса со своими значениями. Время существования и область видимости полей определяется объектом, которому они принадлежат. Объекты в динамической памяти, с которыми не связана ни одна ссылочная переменная, становятся недоступными. Реально они оканчивают свое существование, когда сборщик мусора (garbage collector) выполнит чистку "кучи". Для значимых типов, к которым принадлежат экземпляры структур, жизнь оканчивается при завершении блока, в котором они объявлены.

Есть одно важное исключение. Некоторые поля могут жить дольше. Если при объявлении класса поле объявлено с модификатором static, то такое поле является частью класса и единственным на все его экземпляры. Поэтому static-поля живут так же долго, как и сам класс. Более подробно эти вопросы будут обсуждаться при рассмотрении классов, структур, интерфейсов.

Глобальные переменные уровня модуля. Существуют ли они в С#?

Где еще могут объявляться переменные? Во многих языках программирования переменные могут объявляться на уровне модуля. Такие переменные называются глобальными. Их область действия распространяется, по крайней мере, на весь модуль. Глобальные переменные играют важную роль, поскольку они обеспечивают весьма эффективный способ обмена информацией между различными частями модуля. Обратная сторона эффективности аппарата глобальных переменных, — их опасность. Если какая-либо процедура, в которой доступна глобальная переменная, некорректно изменит ее значение, то ошибка может проявиться в другой процедуре, использующей эту переменную. Найти причину ошибки бывает чрезвычайно трудно. В таких ситуациях приходится проверять работу многих компонентов модуля.

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