- •Спецификация языка
- •1. Введение 1
- •2. Лексическая структура 38
- •3. Основные принципы 61
- •4. Типы 89
- •5. Переменные 107
- •6. Преобразования 126
- •7. Выражения 151
- •8. Операторы языка 265
- •9. Пространства имен 298
- •10. Классы 311
- •11. Структуры 416
- •12. Массивы 429
- •13. Интерфейсы 435
- •18. Небезопасный код 490
- •1.Введение
- •1.1Программа «Hello world»
- •1.2Структура программы
- •1.3Типы и переменные
- •1.4Выражения
- •1.5Операторы языка
- •1.6Классы и объекты
- •1.6.1Члены
- •1.6.2Доступность
- •1.6.3Параметры типа
- •1.6.4Базовые классы
- •1.6.5Поля
- •1.6.6Методы
- •1.6.6.1Параметры
- •1.6.6.2Тело метода и локальные переменные
- •1.6.6.3Статические методы и методы экземпляров
- •1.6.6.4Виртуальные, переопределяющие и абстрактные методы
- •1.6.6.5Перегрузка метода
- •1.6.7Другие члены-функции
- •1.6.7.1Конструкторы
- •1.6.7.2Свойства
- •1.6.7.3Индексаторы
- •1.6.7.4События
- •1.6.7.5Операторы
- •1.6.7.6Деструкторы
- •1.7Структуры
- •1.8Массивы
- •1.9Интерфейсы
- •1.10Перечисления
- •1.11Делегаты
- •1.12Атрибуты
- •2.Лексическая структура
- •2.1Программы
- •2.2Грамматики
- •2.2.1Грамматическая нотация
- •2.2.2Лексика
- •2.2.3Синтаксическая грамматика
- •2.3Лексический анализ
- •2.3.1Знаки завершения строки
- •2.3.2Комментарии
- •2.3.3Пробел
- •2.4Маркеры
- •2.4.1Управляющие последовательности символов Юникода
- •2.4.2Идентификаторы
- •2.4.3Ключевые слова
- •2.4.4Литералы
- •2.4.4.1Логические литералы
- •2.4.4.2Целочисленные литералы
- •2.4.4.3Действительные литералы
- •2.4.4.4Символьные литералы
- •2.4.4.5Строковые литералы
- •2.4.4.6Литерал null
- •2.4.5Операторы и знаки пунктуации
- •2.5Препроцессорные директивы
- •2.5.1Символы условной компиляции
- •2.5.2Препроцессорные выражения
- •2.5.3Директивы объявлений
- •2.5.4Директивы условной компиляции
- •2.5.5Директивы диагностики
- •2.5.6Директивы областей
- •2.5.7Директивы строк
- •2.5.8Директивы pragma
- •2.5.8.1Директива pragma warning
- •3.Основные принципы
- •3.1Запуск приложения
- •3.2Завершение приложения
- •3.3Объявления
- •3.4Члены
- •3.4.1Члены пространства имен
- •3.4.2Члены структуры
- •3.4.3Члены перечисления
- •3.4.4Члены класса
- •3.5.1Объявленная доступность
- •3.5.2Домены доступности
- •3.5.3Защищенный доступ для членов экземпляров.
- •3.5.4Ограничения доступности
- •3.6Сигнатуры и перегрузка
- •3.7Области видимости
- •3.7.1Скрытие имени.
- •3.7.1.1Скрытие через вложение.
- •3.7.1.2Скрытие через наследование
- •3.8Имена пространств имен и типов
- •3.8.1Полные имена
- •3.9Автоматическое управление памятью
- •3.10Порядок выполнения
- •4.1Типы значений
- •4.1.2Конструкторы по умолчанию
- •4.1.3Типы структуры
- •4.1.4Простые типы
- •4.1.5Целые типы
- •4.1.6Типы с плавающей запятой
- •4.1.9Перечисляемые типы
- •4.1.10Обнуляемые типы
- •4.2Ссылочные типы
- •4.2.1Типы классов
- •4.2.2Тип объекта
- •4.2.3Динамический тип
- •4.3Упаковка и распаковка
- •4.3.1Преобразования упаковки
- •4.3.2Преобразования распаковки
- •4.4Сформированные типы
- •4.4.1Аргументы типа
- •4.4.2Открытые и закрытые типы
- •4.4.3Связанные и несвязанные типы
- •4.4.4Соблюдение ограничений
- •4.5Параметры типа
- •4.6Типы дерева выражений
- •4.7Динамический тип
- •5.Переменные
- •5.1Категории переменных
- •5.1.1Статические переменные
- •5.1.2Переменные экземпляра
- •5.1.2.1Переменные экземпляра в классах
- •5.1.2.2Переменные экземпляра в структурах
- •5.1.3Элементы массива
- •5.1.4Параметры по значению
- •5.1.5Параметры по ссылке
- •5.1.6Выходные параметры
- •5.1.7Локальные переменные
- •5.2Значения по умолчанию
- •5.3Определенное присваивание
- •5.3.1Переменные с начальным значением
- •5.3.2Переменные без начального значения
- •5.3.3Точные правила для выявления определенного присваивания
- •5.3.3.1Общие правила для операторов
- •5.3.3.2Операторы блока, операторы checked и unchecked
- •5.3.3.3Операторы-выражения
- •5.3.3.4Операторы объявления
- •5.3.3.5Операторы If
- •5.3.3.6Операторы switch
- •5.3.3.7Операторы while
- •5.3.3.8Операторы do
- •5.3.3.9Операторы for
- •5.3.3.10Операторы break, continue и goto
- •5.3.3.11Операторы throw
- •5.3.3.12Операторы return
- •5.3.3.13Операторы try-catch
- •5.3.3.14Операторы try-finally
- •5.3.3.15Операторы try-catch-finally
- •5.3.3.16Операторы foreach
- •5.3.3.17Операторы using
- •5.3.3.18Операторы lock
- •5.3.3.19Операторы yield
- •5.3.3.20Общие правила для простых выражений
- •5.3.3.21Общие правила для выражений с внедренными выражениями
- •5.3.3.22Выражения вызова и выражения создания объекта
- •5.3.3.23Простые выражения присваивания
- •5.3.3.24Выражения &&
- •5.3.3.25Выражения ||
- •5.3.3.26! Выражения !
- •5.3.3.27?? Выражения ??
- •5.3.3.28Выражения ?:
- •5.3.3.29Анонимные функции
- •5.4Ссылочные переменные
- •5.5Атомарность ссылок на переменные
- •6.Преобразования
- •6.1Неявные преобразования
- •6.1.1Преобразование идентификатора
- •6.1.2Неявные преобразования числовых типов
- •6.1.3Неявные преобразования перечисляемых типов
- •6.1.4Неявные преобразования обнуляемых типов
- •6.1.5Преобразования литерала null
- •6.1.6Неявные преобразования ссылочных типов
- •6.1.7Преобразования упаковки
- •6.1.8Неявные динамические преобразования
- •6.1.9Неявные преобразования выражений констант
- •6.1.10Неявные преобразования, включающие параметры типа
- •6.1.11Пользовательские неявные преобразования
- •6.1.12Преобразования анонимных функций и преобразования группы методов
- •6.2Явные преобразования
- •6.2.1Явные преобразования числовых типов
- •6.2.2Явные преобразования перечисляемых типов
- •6.2.3Явные преобразования обнуляемых типов
- •6.2.4Явные преобразования ссылочных типов
- •6.2.5Преобразования распаковки
- •6.2.6Неявные динамические преобразования
- •6.2.7Явные преобразования, включающие параметры типа
- •6.2.8Пользовательские явные преобразования
- •6.3Стандартные преобразования
- •6.3.1Стандартные неявные преобразования
- •6.3.2Стандартные явные преобразования
- •6.4Пользовательские преобразования
- •6.4.1Допустимые пользовательские преобразования
- •6.4.2Операторы преобразования с нулификацией
- •6.4.3Вычисление пользовательских преобразований
- •6.4.4Определенные пользователем неявные преобразования
- •6.4.5Определенные пользователем явные преобразования
- •6.5Преобразования анонимных функций
- •6.5.1Вычисление преобразования анонимной функции к типу делегата
- •6.5.2Вычисление преобразования анонимной функции к типу дерева выражений
- •6.5.3Пример реализации
- •6.6Преобразования группы методов
- •7.Выражения
- •7.1Классы выражений
- •7.1.1Значения выражений
- •7.2Статическая и динамическая привязка
- •7.2.1Время привязки
- •7.2.2Динамическая привязка
- •7.2.3Типы составных выражений
- •7.3Операторы
- •7.3.1Приоритет и ассоциативность операторов
- •7.3.2Перегрузка операторов
- •7.3.3Разрешение перегрузки унарных операторов
- •7.3.4Разрешение перегрузки бинарных операторов
- •7.3.5Пользовательские операторы-кандидаты
- •7.3.6Числовое расширение
- •7.3.6.1Числовое расширение унарных операторов
- •7.3.6.2Числовое расширение бинарных операторов
- •7.3.7Операторы с нулификацией
- •7.4Поиск членов
- •7.4.1Базовые типы
- •7.5Функции-члены
- •7.5.1Списки аргументов
- •7.5.1.1Соответствующие параметры
- •7.5.1.2Вычисление списков аргументов во время выполнения
- •7.5.2Вывод типа
- •7.5.2.1Первый этап
- •7.5.2.2Второй этап
- •7.5.2.3Типы ввода
- •7.5.2.4 Типы вывода
- •7.5.2.5Зависимость
- •7.5.2.6Вывод типа вывода
- •7.5.2.7Вывод явных типов параметров
- •7.5.2.8Точный вывод
- •7.5.2.9Вывод нижних границ
- •7.5.2.10Вывод по верхним границам
- •7.5.2.11Фиксирование
- •7.5.2.12Выведенный тип возвращаемого значения
- •7.5.2.13Вывод типа при преобразовании групп методов
- •7.5.2.14Поиск наиболее подходящего общего типа для набора выражений
- •7.5.3Разрешение перегрузки
- •7.5.3.1Применимая функция-член
- •7.5.3.2Более подходящая функция-член
- •7.5.3.3Лучшее преобразование из выражения
- •7.5.3.4Лучшее преобразование из типа
- •7.5.3.5Лучшая цель для преобразования
- •7.5.3.6Перегрузка в универсальных классах
- •7.5.4Проверка динамического разрешения перегрузки во время компиляции
- •7.5.5Вызов функции-члена
- •7.5.5.1Вызов в упакованных экземплярах
- •7.6Первичные выражения
- •7.6.1Литералы
- •7.6.2Простые имена
- •7.6.2.1Инвариантность значения в блоках
- •7.6.3Выражения со скобками
- •7.6.4Доступ к члену
- •7.6.4.1Идентичные простые имена и имена типов
- •7.6.4.2Грамматическая неоднозначность
- •7.6.5Выражения вызова
- •7.6.5.1Вызовы методов
- •7.6.5.2Вызовы методов расширения
- •7.6.5.3Вызовы делегатов
- •7.6.6Метод доступа к элементу
- •7.6.6.1Доступ к массиву
- •7.6.6.2Доступ к индексатору
- •7.6.7Доступ this
- •7.6.8Доступ base
- •7.6.9Постфиксные операторы инкремента и декремента
- •7.6.10Оператор new
- •7.6.10.1Выражения создания объектов
- •7.6.10.2Инициализаторы объектов
- •7.6.10.3Инициализаторы коллекции
- •7.6.10.4Выражения создания массива
- •7.6.10.5Выражения создания делегата
- •7.6.10.6Выражения создания анонимных объектов
- •7.6.11Оператор typeof
- •7.6.12Операторы checked и unchecked
- •7.6.13Выражения значения по умолчанию
- •7.6.14Выражения анонимного метода
- •7.7Унарные операторы
- •7.7.1Унарный оператор «плюс»
- •7.7.2Унарный оператор «минус»
- •7.7.3Оператор логического отрицания
- •7.7.4Оператор побитового дополнения
- •7.7.5Префиксные операторы инкремента и декремента
- •7.7.6Выражения приведения типа
- •7.8Арифметические операторы
- •7.8.1Оператор произведения
- •7.8.2Оператор деления
- •7.8.3Оператор остатка
- •7.8.4Оператор сложения
- •7.8.5Оператор вычитания
- •7.9Операторы сдвига
- •7.10Операторы отношения и проверки типа
- •7.10.1Операторы сравнения целых чисел
- •7.10.2Операторы сравнения чисел с плавающей запятой
- •7.10.3Операторы сравнения десятичных чисел
- •7.10.4Логические операторы равенства
- •7.10.5Операторы сравнения значений перечисления
- •7.10.6Операторы равенства значений ссылочного типа
- •7.10.7Операторы равенства строк
- •7.10.8Операторы равенства делегатов
- •7.10.9Операторы равенства и значение null
- •7.10.10Оператор is
- •7.10.11Оператор as
- •7.11Логические операторы
- •7.11.1Логические операторы для целых чисел
- •7.11.2Логические операторы для перечислений
- •7.11.3Логические операторы
- •7.11.4Обнуляемые логические операторы
- •7.12Условные логические операторы
- •7.12.1Логические условные операторы
- •7.12.2Пользовательские условные логические операторы
- •7.13Оператор слияния с null
- •7.14Условный оператор
- •7.15Выражения анонимных функций
- •7.15.1Сигнатуры анонимных функций
- •7.15.2Тела анонимных функций
- •7.15.3Разрешение перегрузки
- •7.15.4Анонимные функции и динамическая привязка
- •7.15.5Внешние переменные
- •7.15.5.1Захваченные внешние переменные
- •7.15.5.2Создание экземпляров локальных переменных
- •7.15.6Вычисление выражений анонимных функций
- •7.16Выражения запросов
- •7.16.1Неоднозначность в выражениях запросов
- •7.16.2Перевод выражений запросов
- •7.16.2.1Предложения select и groupby с продолжениями
- •7.16.2.2Явные типы переменных диапазона
- •7.16.2.3Выражения вырожденных запросов
- •7.16.2.4Предложения from, let, where, join и orderby
- •7.16.2.5Предложения select
- •7.16.2.6Предложения groupby
- •7.16.2.7Прозрачные идентификаторы
- •7.16.3Шаблон выражения запроса
- •7.17Операторы присваивания
- •7.17.1Простое присваивание
- •7.17.2Сложное присваивание
- •7.17.3Присваивание событий
- •7.18Выражение
- •7.19Константные выражения
- •7.20Логические выражения
- •8.Операторы языка
- •8.1Конечные точки и достижимость
- •8.2Блоки
- •8.2.1Списки операторов
- •8.3Пустой оператор
- •8.4Помеченные операторы
- •8.5Операторы объявления
- •8.5.1Объявления локальных переменных
- •8.5.2Объявления локальных констант
- •8.6Операторы-выражения
- •8.7Операторы выбора
- •8.7.1Оператор if
- •8.7.2Оператор switch
- •8.8Операторы итераций
- •8.8.1Оператор while
- •8.8.2Оператор do
- •8.8.3Оператор for
- •8.8.4Оператор foreach
- •8.9Операторы перехода
- •8.9.1Оператор break
- •8.9.2Оператор continue
- •8.9.3Оператор goto
- •8.9.4Оператор return
- •8.9.5Оператор throw
- •8.10Оператор try
- •8.11Операторы checked и unchecked
- •8.12Оператор lock
- •8.13Оператор using
- •8.14Оператор yield
- •9.Пространства имен
- •9.1Единицы компиляции
- •9.2Объявления пространства имен
- •9.3Внешние псевдонимы
- •9.4Директивы using
- •9.4.1Директивы using alias
- •9.4.2Директивы using namespace
- •9.5Члены пространства имен
- •9.6Объявления типов
- •9.7Квалификаторы псевдонима пространства имен
- •9.7.1Уникальность псевдонимов
- •10.Классы
- •10.1Объявления классов
- •10.1.1Модификаторы классов
- •10.1.1.1Абстрактные классы
- •10.1.1.2Запечатанные классы
- •10.1.1.3Статические классы
- •10.1.1.3.1Ссылки на типы статического класса
- •10.1.2Модификатор partial
- •10.1.3Параметры типа
- •10.1.4Спецификация базы класса
- •10.1.4.1Базовые классы
- •10.1.4.2Реализация интерфейсов
- •10.1.5Ограничения параметров типа
- •10.1.6Тело класса
- •10.2Разделяемые типы
- •10.2.1Атрибуты
- •10.2.2Модификаторы
- •10.2.3Параметры и ограничения типа
- •10.2.4Базовый класс
- •10.2.5Базовые интерфейсы
- •10.2.6Члены
- •10.2.7Разделяемые методы
- •10.2.8Привязка имен
- •10.3Члены класса
- •10.3.1Тип экземпляра
- •10.3.2Члены сформированных типов
- •10.3.3Наследование
- •10.3.4Модификатор new
- •10.3.5Модификаторы доступа
- •10.3.6Составные типы
- •10.3.7Статические члены и члены экземпляра
- •10.3.8Вложенные типы
- •10.3.8.1Полные имена
- •10.3.8.2Объявленная доступность
- •10.3.8.3Скрытие
- •10.3.8.4Доступ this
- •10.3.8.5Доступ к частным и защищенным членам типа-контейнера
- •10.3.8.6Вложенные типы в универсальных классах
- •10.3.9Зарезервированные имена членов
- •10.3.9.1Имена членов, зарезервированные для свойств
- •10.5Поля
- •10.5.1Статические поля и поля экземпляров
- •10.5.2Поля только для чтения
- •10.5.2.1Использование статических полей только для чтения вместо констант
- •10.5.2.2Отслеживание версий констант и статических полей только для чтения
- •10.5.3Поля с модификатором volatile
- •10.5.4Инициализация поля
- •10.5.5Инициализаторы переменных
- •10.5.5.1Инициализация статического поля
- •10.5.5.2Инициализация поля экземпляра
- •10.6Методы
- •10.6.1Параметры метода
- •10.6.1.1Параметры по значению
- •10.6.1.2Параметры по ссылке
- •10.6.1.3Выходные параметры
- •10.6.1.4Массивы параметров
- •10.6.2Статические методы и методы экземпляра
- •10.6.3Виртуальные методы
- •10.6.4Переопределяющие методы
- •10.6.5Запечатанные методы
- •10.6.6Абстрактные методы
- •10.6.7Внешние методы
- •10.6.8Разделяемые методы
- •10.6.9Методы расширения
- •10.6.10Тело метода
- •10.6.11Перегрузка метода
- •10.7Свойства
- •10.7.1Статические свойства и свойства экземпляра
- •10.7.2Методы доступа
- •10.7.3Автоматически реализуемые свойства
- •10.7.4Доступность
- •10.7.5Виртуальные, запечатанные, переопределяющие и абстрактные методы доступа
- •10.8События
- •10.8.1События, подобные полям
- •10.8.2Методы доступа к событиям
- •10.8.3Статические события и события экземпляров
- •10.8.4Виртуальные, запечатанные, переопределяющие и абстрактные методы доступа
- •10.9Индексаторы
- •10.9.1Перегрузка индексатора
- •10.10Операторы
- •10.10.1Унарные операторы
- •10.10.2Бинарные операторы
- •10.10.3Операторы преобразования
- •10.11Конструкторы экземпляров
- •10.11.1Инициализаторы конструкторов
- •10.11.2Инициализаторы переменных экземпляров
- •10.11.3Выполнение конструктора
- •10.11.4Конструкторы по умолчанию
- •10.11.5Закрытые конструкторы
- •10.11.6Необязательные параметры конструктора экземпляров
- •10.12Статические конструкторы
- •10.13Деструкторы
- •10.14Итераторы
- •10.14.1Интерфейсы перечислителя
- •10.14.2Перечислимые интерфейсы
- •10.14.4Объекты перечислителя
- •10.14.4.1Метод MoveNext
- •10.14.4.2Свойство Current
- •10.14.4.3Метод Dispose
- •10.14.5Перечислимые объекты
- •10.14.5.1Метод GetEnumerator
- •10.14.6Пример реализации
- •11.Структуры
- •11.1Объявления структур
- •11.1.1Модификаторы структуры
- •11.3Различия между классом и структурой
- •11.3.1Семантика значений
- •11.3.2Наследование
- •11.3.3Присваивание
- •11.3.4Значения по умолчанию
- •11.3.5Упаковка и распаковка
- •11.3.6Действие ключевого слова this
- •11.3.7Инициализаторы полей
- •11.3.8Конструкторы
- •11.3.9Деструкторы
- •11.3.10Статические конструкторы
- •11.4Примеры структур
- •11.4.1Тип целочисленного значения в базе данных
- •11.4.2Логический тип базы данных
- •12.Массивы
- •12.1Типы массива
- •12.1.2Массивы и универсальный интерфейс iList
- •12.2Создание массива
- •12.3Доступ к элементам массива
- •12.4Члены массива
- •12.5Ковариация массивов
- •12.6Инициализаторы массива
- •13.Интерфейсы
- •13.1Объявления интерфейсов
- •13.1.1Модификаторы интерфейса
- •13.1.2Модификатор partial
- •13.1.3Списки параметров типа варианта
- •13.1.3.1Безопасность вариативности
- •13.1.3.2Вариантные преобразования
- •13.1.4Базовые интерфейсы
- •13.1.5Тело интерфейса
- •13.2Члены интерфейса
- •13.2.1Методы интерфейса
- •13.2.2Свойства интерфейса
- •13.2.3События интерфейса
- •13.2.4Индексаторы интерфейса
- •13.2.5Доступ к членам интерфейса
- •13.3Полные имена членов интерфейса
- •13.4Реализация интерфейсов
- •13.4.1Явные реализации членов интерфейса
- •13.4.2Уникальность реализованных интерфейсов
- •13.4.3Реализация универсальных методов
- •13.4.4Сопоставление интерфейсов
- •13.4.5Наследование реализаций интерфейсов
- •13.4.6Повторная реализация интерфейса
- •13.4.7Абстрактные классы и интерфейсы
- •14.Перечисляемые типы
- •14.1Объявления перечислений
- •14.2Модификаторы перечисления
- •14.3Члены перечисления
- •14.5Значения перечисления и операции
- •15.Делегаты
- •15.1Объявления делегатов
- •15.2Совместимость делегатов
- •15.3Создание экземпляра делегата
- •15.4Вызов делегата
- •16.Исключения
- •16.1Причины исключений
- •16.2Класс System.Exception
- •16.3Обработка исключений
- •16.4Общие классы исключений
- •17.Атрибуты
- •17.1Классы атрибутов
- •17.1.1Использование атрибутов
- •17.1.2Позиционные и именованные параметры
- •17.1.3Типы параметров атрибута
- •17.2Спецификация атрибута
- •17.3Экземпляры атрибутов
- •17.3.1Компиляция атрибута
- •17.3.2Извлечение экземпляра атрибута во время выполнения
- •17.4Зарезервированные атрибуты
- •17.4.1Атрибут AttributeUsage
- •17.4.2Атрибут Conditional
- •17.4.2.1Условные методы
- •17.4.2.2Классы условных атрибутов
- •17.4.3Атрибут Obsolete
- •17.5Атрибуты для взаимодействия
- •17.5.1Взаимодействие с компонентами com и Win32
- •17.5.2Взаимодействие с другими языками .Net
- •17.5.2.1Атрибут IndexerName
- •18.Небезопасный код
- •18.1Небезопасные контексты
- •18.2Типы указателя
- •18.3Фиксированные и перемещаемые переменные
- •18.4Преобразования указателей
- •18.4.1 Массивы указателей
- •18.5Указатели в выражениях
- •18.5.1Косвенное обращение по указателю
- •18.5.2Доступ к члену по указателю
- •18.5.3Доступ к элементу по указателю
- •18.5.4Оператор адреса
- •18.5.5Увеличение и уменьшение указателя
- •18.5.6Арифметические операции с указателем
- •18.5.7Сравнение указателей
- •18.5.8Оператор sizeof
- •18.6Оператор fixed
- •18.7Буферы фиксированного размера
- •18.7.1Объявления буферов фиксированного размера
- •18.7.2Буферы фиксированного размера в выражениях
- •18.7.3Проверка определенного присваивания
- •18.8Выделение стека
- •18.9Динамическое выделение памяти
- •Комментарии к документации
- •Введение
- •Рекомендованные теги
- •Обработка файла документации
- •Формат строки идентификатора
- •Примеры строк идентификаторов
- •Исходный код c#
- •Результирующий xml
- •Ключевые слова
- •Литералы
- •Операторы и знаки пунктуации
- •Директивы предварительной обработки
- •Синтаксис
- •Основные принципы
- •Переменные
- •Выражения
- •Операторы
- •Пространства имен
- •Структуры
- •Массивы
- •Интерфейсы
- •Перечисления
- •Делегаты
- •Атрибуты
- •Грамматические расширения для небезопасного кода
- •© Корпорация Майкрософт (Microsoft Corp.), 1999-20101998. Все права защищены. Присылайте нам свои исправления, комментарии, отзывы и предложения по адресу csharp@microsoft.Com
17.1.3Типы параметров атрибута
Типы позиционных и именованных параметров для класса атрибута ограничены типами параметров атрибута, к которым относятся:
один из следующих типов: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong и ushort;
тип object;
тип System.Type;
перечисляемый тип, если и он имеет общую доступность, и типы, в которые он вложен (если вложен), также имеют общую доступность (§17.2);
одномерные массивы указанных выше типов.
Аргумент конструктора или общее поле, которые не имеют один из этих типов, не могут использоваться в качестве позиционных или именованных параметров в спецификации атрибута.
17.2Спецификация атрибута
Спецификация атрибута — это применение предварительно определенного атрибута к объявлению. Атрибут является частью дополнительных декларативных сведений, задаваемых для объявления. Атрибуты могут задаваться в глобальной области видимости (чтобы задать атрибуты для содержащей сборки или модуля) и для объявлений_типов (§9.6), объявлений_членов_класса (§10.1.5), объявлений_членов_интерфейса (§13.2), объявлений_членов_структуры (§11.2), объявлений_членов_перечисления (§14.3), объявлений_методов_доступа (§10.7.2), объявлений_метода_доступа_к_событиям (§10.8.1) и списков_формальных_параметров (§10.6.1).
Атрибуты задаются в разделах атрибутов. Раздел атрибутов состоит из пары квадратных скобок, которые окружают список из одного или более атрибутов, разделенных запятыми. Порядок указания атрибутов в таком списке и порядок размещения разделов, вложенных в одну и ту же программную сущность, не имеет значения. Например, спецификации атрибутов [A][B], [B][A], [A, B] и [B, A] эквивалентны.
глобальные_атрибуты: разделы_глобальных_атрибутов
разделы_глобальных_атрибутов: раздел_глобальных_атрибутов разделы_глобальных_атрибутов раздел_глобальных_атрибутов
раздел_глобальных_атрибутов: [ целевая_спецификация_глобального_атрибута список_атрибутов ] [ целевая_спецификация_глобального_атрибута список_атрибутов , ]
целевая_спецификация_глобального_атрибута: цель_глобального_атрибута :
цель_глобального_атрибута: assembly module
атрибуты: разделы_атрибутов
разделы_атрибутов: раздел_атрибутов разделы_атрибутов раздел_атрибутов
раздел_атрибутов: [ целевая_спецификация_атрибутанеобязательно список_атрибутов ] [ целевая_спецификация_атрибутанеобязательно список_атрибутов , ]
целевая_спецификация_атрибута: цель_атрибута :
цель_атрибута: field event method param property return type
список_атрибутов: атрибут список_атрибутов , атрибут
атрибут: имя_атрибута аргументы_атрибутанеобязательно
имя_атрибута: имя_типа
аргументы_атрибута: ( список_аргументов_по_положениюнеобязательно ) ( список_аргументов_по_положению , список_именованных_аргументов ) ( список_именованных_аргументов )
список_аргументов_по_положению: аргумент_по_положению список_аргументов_по_положению , аргумент_по_положению
аргумент_по_положению: имя_аргументанеобязательно выражение_аргумента_атрибута
список_именованных_аргументов: именованный_аргумент список_именованных_аргументов , именованный_аргумент
именованный_аргумент: идентификатор = выражение_аргумента_атрибута
выражение_аргумента_атрибута: выражение
Атрибут состоит из имени_атрибута и необязательного списка позиционных и именованных аргументов. Позиционные аргументы (если они имеются) предшествуют именованным аргументам. Позиционный аргумент состоит из выражения_аргумента_атрибута; именованный аргумент состоит из имени, за которым следует знак равенства, далее следует выражение_аргумента_атрибута, которые все вместе ограничены теми же правилами, которые применяются для простого присваивания. Порядок именованных аргументов не имеет значения.
Имя_атрибута идентифицирует класс атрибута. Если имя_атрибута имеет вид имени_типа, это имя должно ссылаться на класс атрибута. В противном случае произойдет ошибка времени компиляции. Например:
class Class1 {}
[Class1] class Class2 {} // Error
В результате возникает ошибка времени компиляции, так как предпринята попытка использовать Class1 в качестве класса атрибута, хотя Class1 не является классом атрибута.
Определенные контексты разрешают спецификацию атрибута более чем для одного целевого объекта. Программа может явно задать целевой объект включением описателя_целевого_объекта_атрибута. Если атрибут размещен на глобальном уровне, требуется описатель_целевого_объекта_глобального_атрибута. Во всех остальных расположениях применяется обоснованное значение по умолчанию, но описатель_целевого_объекта_атрибута может использоваться для подтверждения или переопределения значения по умолчанию в определенных неоднозначных ситуациях (или просто для подтверждения значения по умолчанию в не вызывающих сомнения случаях). Таким образом, описатели_целевого_объекта_атрибута обычно могут быть опущены, кроме случаев их использования на глобальном уровне. В случае потенциально неоднозначных контекстов решение принимается следующим образом:
атрибут, заданный в глобальной области видимости, может применяться либо к конечной сборке, либо к конечному модулю. Для этого контекста нет значения по умолчанию, поэтому в этом контексте всегда требуется описатель_целевого_объекта_атрибута. Наличие описателя_целевого_объекта_атрибута assembly указывает, что атрибут применяется к конечной сборке; наличие описателя_целевого_объекта_атрибута module указывает, что атрибут применяется к конечному модулю;
атрибут, заданный в объявлении делегата, может применяться либо к объявляемому делегату, либо к его возвращаемому значению. При отсутствии описателя_целевого_объекта_атрибута атрибут применяется к делегату. Наличие описателя_целевого_объекта_атрибута type указывает, что атрибут применяется к делегату; наличие описателя_целевого_объекта_атрибута return указывает, что атрибут применяется к возвращаемому значению;
атрибут, заданный в объявлении метода, может применяться либо к объявляемому методу, либо к его возвращаемому значению. При отсутствии описателя_целевого_объекта_атрибута атрибут применяется к методу. Наличие описателя_целевого_объекта_атрибута method указывает, что атрибут применяется к методу; наличие описателя_целевого_объекта_атрибута return указывает, что атрибут применяется к возвращаемому значению;
атрибут, заданный в объявлении оператора, может применяться либо к объявляемому оператору, либо к его возвращаемому значению. При отсутствии описателя_целевого_объекта_атрибута атрибут применяется к оператору. Наличие описателя_целевого_объекта_атрибута method указывает, что атрибут применяется к методу; наличие описателя_целевого_объекта_атрибута return указывает, что атрибут применяется к возвращаемому значению;
атрибут, заданный в объявлении события, в котором опущены методы доступа к событиям, может применяться к объявляемому событию, к связанному полю (если событие не является абстрактным) или к связанным методам add и remove. При отсутствии описателя_целевого_объекта_атрибута атрибут применяется к событию. Наличие описателя_целевого_объекта_атрибута event указывает, что атрибут применяется к событию; наличие описателя_целевого_объекта_атрибута field указывает, что атрибут применяется к полю; а наличие описателя_целевого_объекта_атрибута method указывает, что атрибут применяется к методам;
атрибут, заданный в объявлении метода доступа get для объявления свойства или индексатора, может применяться либо к связанному методу, либо к его возвращаемому значению. При отсутствии описателя_целевого_объекта_атрибута атрибут применяется к методу. Наличие описателя_целевого_объекта_атрибута method указывает, что атрибут применяется к методу; наличие описателя_целевого_объекта_атрибута return указывает, что атрибут применяется к возвращаемому значению;
атрибут, указанный в объявлении метода доступа set для объявления свойства или индексатора, может применяться либо к связанному методу, либо к его одиночному неявному параметру. При отсутствии описателя_целевого_объекта_атрибута атрибут применяется к методу. Наличие описателя_целевого_объекта_атрибута method указывает, что атрибут применяется к методу; наличие описателя_целевого_объекта_атрибута param указывает, что атрибут применяется к параметру; наличие описателя_целевого_объекта_атрибута return указывает, что атрибут применяется к возвращаемому значению;
атрибут, заданный в объявлении метода доступа add или remove для объявления события, может применяться или к связанному методу, или к его одиночному параметру. При отсутствии описателя_целевого_объекта_атрибута атрибут применяется к методу. Наличие описателя_целевого_объекта_атрибута method указывает, что атрибут применяется к методу; наличие описателя_целевого_объекта_атрибута param указывает, что атрибут применяется к параметру; наличие описателя_целевого_объекта_атрибута return указывает, что атрибут применяется к возвращаемому значению.
В других контекстах включение описателя_целевого_объекта_атрибута разрешено, но излишне. Например, объявление класса может или включать, или опускать описатель type:
[type: Author("Brian Kernighan")] class Class1 {}
[Author("Dennis Ritchie")] class Class2 {}
Является ошибкой задание недопустимого описателя_целевого_объекта_атрибута. Например, описатель param нельзя использовать в объявлении класса:
[param: Author("Brian Kernighan")] // Error class Class1 {}
Классы атрибутов принято именовать с помощью суффикса Attribute. Имя_атрибута вида имя_типа может или включать, или опускать этот суффикс. Если обнаружен класс атрибута и с этим суффиксом, и без суффикса, эта неоднозначность приводит к ошибке времени компиляции. Если имя_атрибута записывается таким образом, что его самый правый идентификатор является буквальным идентификатором (§2.4.2), то сопоставляется только атрибут без суффикса, позволяя таким образом разрешить неоднозначность. Например:
using System;
[AttributeUsage(AttributeTargets.All)] public class X: Attribute {}
[AttributeUsage(AttributeTargets.All)] public class XAttribute: Attribute {}
[X] // Error: ambiguity class Class1 {}
[XAttribute] // Refers to XAttribute class Class2 {}
[@X] // Refers to X class Class3 {}
[@XAttribute] // Refers to XAttribute class Class4 {}
Здесь показаны два класса атрибутов с именами X и XAttribute. Атрибут [X] является неоднозначным, так как он может ссылаться или на X, или на XAttribute. Использование буквального идентификатора позволяет указать точное намерение в таких редких случаях. Атрибут [XAttribute] не является неоднозначным (хотя он мог бы им быть, если бы имелся класс атрибута с именем XAttributeAttribute). Если удаляется объявление для класса X, то оба атрибута ссылаются на класс атрибута с именем XAttribute, как это показано в следующем примере:
using System;
[AttributeUsage(AttributeTargets.All)] public class XAttribute: Attribute {}
[X] // Refers to XAttribute class Class1 {}
[XAttribute] // Refers to XAttribute class Class2 {}
[@X] // Error: no attribute named "X" class Class3 {}
Использование класса атрибута одноразового использования более одного раза для одной и той же сущности является ошибкой времени компиляции. Например:
using System;
[AttributeUsage(AttributeTargets.Class)] public class HelpStringAttribute: Attribute { string value;
public HelpStringAttribute(string value) { this.value = value; }
public string Value { get {...} } }
[HelpString("Description of Class1")] [HelpString("Another description of Class1")] public class Class1 {}
В результате возникает ошибка времени компиляции, так как предпринимается попытка использования HelpString, который является классом атрибута одноразового использования, более одного раза в объявлении Class1.
Выражение E является выражением_аргумента_атрибута, если верны все следующие утверждения:
тип E — это тип параметра атрибута (§17.1.3);
во время компиляции значение E может быть разрешено в одно из следующего:
постоянное значение;
объект System.Type;
одномерный массив выражений_аргумента_атрибута.
Пример:
using System;
[AttributeUsage(AttributeTargets.Class)] public class TestAttribute: Attribute { public int P1 { get {...} set {...} }
public Type P2 { get {...} set {...} }
public object P3 { get {...} set {...} } }
[Test(P1 = 1234, P3 = new int[] {1, 3, 5}, P2 = typeof(float))] class MyClass {}
Выражение_typeof (§7.6.11), используемое в качестве выражения аргумента атрибута, может ссылаться на неуниверсальный тип, закрытый сконструированный тип или на несвязанный универсальный тип, но не может ссылаться на открытый тип. Это обеспечивает возможность разрешения выражения во время компиляции.
class A: Attribute { public A(Type t) {...} }
class G<T> { [A(typeof(T))] T t; // Error, open type in attribute }
class X { [A(typeof(List<int>))] int x; // Ok, closed constructed type [A(typeof(List<>))] int y; // Ok, unbound generic type }