Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

3.7Области видимости

Областью видимости имени является часть текста программы, в рамках которой можно ссылаться на сущность, объявленную именем без квалификации имени. Области могут быть вложенные, а внутренняя область может повторно объявлять значение имени из внешней области (однако это не снимает ограничение, наложенное §3.3, что в рамках вложенного блока невозможно объявить локальную переменную с именем, совпадающим с именем локальной переменной во внешнем блоке). Имя из внешней области при этом считается скрытым в регионе текста программы, покрываемом внутренней областью, а доступ к внешнему имени возможен только по квалифицирующему имени.

  • Областью члена пространства имен, объявленного объявлением_члена_пространства_имен (§9.5), без вмещающего объявления_пространства_имен является полный текст программы.

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

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

  • Область имени, заданная или импортированная путем использования_директивы (§9.4), распространяется на объявления_членов_пространства_имен_блока_компиляции или тела_пространства_имен, в котором содержится использование_директивы. Использование_директивы может привести к образованию нуля или более пространств имен или типов имен, доступных в рамках определенного блока_компиляции или тела_пространства_имен, но не может привести к созданию новых членов в нижестоящей области объявления. Другими словами, использование_директивы не является транзитивным, а скорее влияет только на блок_компиляции или тело_пространства_имен, в котором находится.

  • Областью параметра типа, объявленного списком_параметров_типа в объявлении_класса (§10.1), является база_класса, предложения_ограничений_параметров_типа и тело_класса данного объявления_класса.

  • Областью параметра типа, объявленного списком_параметров_типа в объявлении_структуры (§11.1), является интерфейс_структуры, предложения_ограничений_параметров_типа и тело_структуры данного объявления_структуры.

  • Областью параметра типа, объявленного списком_параметров_типа в объявлении_интерфейса (§13.1), является база_интерфейса, предложения_ограничений_параметров_типа и тело_интерфейса данного объявления_интерфейса.

  • Областью параметра типа, объявленного списком_параметров_типа в объявлении_делегата (§15.1), является тип_возвращаемого_значения, список_формальных_параметров и предложения_ограничений_параметров_типа данного объявления_делегата.

  • Областью члена, объявленного объявлением_члена_класса (§10.1.6), является тело_класса, в котором сделано объявление. Кроме того, область члена класса распространяется на тела_класса производных классов, включенных в домен доступности (§3.5.2) члена.

  • Областью члена, объявленного объявлением_члена_структуры (§11.2), является тело_структуры, в котором сделано объявление.

  • Областью члена, объявленного объявлением_члена_перечисляемого_типа (§14.3), является тело_перечисляемого_типа, в котором сделано объявление.

  • Областью параметра, объявленного в объявлении_метода (§10.6), является тело_метода данного объявления_метода.

  • Областью параметра, объявленного в объявлении_индексатора (§10.9), являются объявления_метода_доступа данного объявления_индексатора.

  • Областью параметра, объявленного в объявлении_оператора (§10.10), является блок данного объявления_оператора.

  • Областью параметра, объявленного в объявлении_конструктора (§10.11), является инициализатор_конструктора и блок данного объявления_конструктора.

  • Областью параметра, объявленного в лямбда_выражении (§), является тело_лямбда_выражения данного лямбда_выражения.

  • Областью параметра, объявленного в выражении_анонимного_метода (§), является блок данного выражения_анонимного_метода.

  • Областью метки, объявленной в помеченном_операторе (§8.4), является блок, в котором содержится объявление.

  • Областью локальной переменной, объявленной в объявлении_локальной_переменной (§8.5.1), является блок, в котором содержится объявление.

  • Областью локальной переменной, объявленной в блоке_ветвления оператора switch (§8.7.2), является блок_ветвления.

  • Областью локальной переменной, объявленной в инициализаторе_for оператора for (§8.8.3), является инициализатор_for, условие_for, итератор_for и содержащий оператор оператора for.

  • Областью локальной константы, объявленной в объявлении_локальной_константы (§8.5.2), является блок, в котором содержится объявление. Ссылка на локальную константу в текстовой позиции, предшествующей декларатору_константы, является ошибкой времени компилирования.

  • Область переменной, объявленной в качестве части оператора_foreach, оператора_using, оператора_lock или выражения_запроса, определяется путем расширения заданной конструкции.

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

class A { void F() { i = 1; }

int i = 0; }

В данном примере ссылка F на i до объявления является верной.

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

class A { int i = 0;

void F() { i = 1; // Error, use precedes declaration int i; i = 2; }

void G() { int j = (j = 1); // Valid }

void H() { int a = 1, b = ++a; // Valid } }

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

Правила назначения областей для локальных переменных разработаны для того, чтобы значение имени в контексте выражения использовалось только в рамках блока. Если область локальной переменной расширена только из объявления до конца блока, в вышеуказанном примере первое присваивание будет присвоено переменной экземпляра, второе присваивание будет присвоено локальной переменной, что, возможно, приведет к ошибкам времени компилирования, если операторы блока будут затем переупорядочены.

Значение имени в рамках блока может отличаться в зависимости от контекста, в котором используется имя. Пример:

using System;

class A {}

class Test { static void Main() { string A = "hello, world"; string s = A; // expression context

Type t = typeof(A); // type context

Console.WriteLine(s); // writes "hello, world" Console.WriteLine(t); // writes "A" } }

имя A используется в контексте выражения для ссылки на локальную переменную A и в контексте типа для ссылки на класс A.

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