- •Спецификация языка
- •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
14.5Значения перечисления и операции
Каждый перечисляемый тип определяет отдельный тип; требуется явное преобразование перечисления (§6.2.2), чтобы выполнить преобразование между перечисляемым типом и целым типом, или между двумя перечисляемыми типами. Набор значений, которые может принимать перечисляемый тип, не ограничен его членами перечисления. А именно, любое значение базового типа перечисления может быть приведено к перечисляемому типу, и оно является отдельным допустимым значением этого перечисляемого типа.
Члены перечисления имеют тип содержащего их перечисляемого типа (кроме случаев, когда они входят в инициализаторы других членов перечисления: см. §14.3). Значением члена перечисления, объявленного в перечисляемом типе E со связанным значением v, является (E)v.
Со значениями перечисляемых типов могут использоваться следующие операторы: ==, !=, <, >, <=, >= (§7.10.5), бинарный + (§7.8.4), бинарный ‑ (§7.8.5), ^, &, | (§7.11.2), ~ (§7.7.4), ++ и -- (§7.6.9 и §7.7.5) и (§7.7.5).
Каждый перечисляемый тип автоматически производится от класса System.Enum (который в свою очередь производится от System.ValueType и object). Таким образом, унаследованные методы и свойства этого класса могут использоваться в значениях перечисляемого типа.
15.Делегаты
Делегаты делают возможными сценарии, которые в других языках, таких как C++, Pascal и Modula, реализуются с помощью указателей на функции. Однако в отличие от указателей на функции языка C++, делегаты являются полностью объектно-ориентированными, и в отличие от указателей на функции-члены языка C++, делегаты инкапсулируют и экземпляр объекта, и метод.
Объявление делегата определяет класс, производный от класса System.Delegate. Экземпляр делегата инкапсулирует список вызова, являющийся списком из одного или более методов, на каждый из которых ссылаются как на объект, допускающий вызов. Для методов экземпляров объект, допускающий вызов, состоит из экземпляра и метода для этого экземпляра. Для статических методов объект, допускающий вызов, состоит только из метода. Вызов экземпляра делегата с соответствующим набором аргументов приводит к вызову каждого из допускающих вызов объектов делегата с данным набором аргументов.
Интересным и полезным свойством экземпляра делегата является то, что он не знает и не заботится о классах методов, которые инкапсулирует; имеет значение только совместимость этих методов (§15.1) с типом делегата. Это делает делегаты вполне пригодными для «анонимного» вызова.
15.1Объявления делегатов
Объявление_делегата — это объявление_типа (§9.6), которое объявляет новый тип делегата.
объявление_делегата: атрибутынеобязательно модификаторы_делегатанеобязательно delegate возвращаемый_тип идентификатор список_параметров_типа_вариантанеобязательно ( список_формальных_параметровнеобязательно ) предложения_ограничений_параметров_типанеобязательно ;
модификаторы_делегата: модификатор_делегата модификатор_делегата модификаторы_делегата
модификатор_делегата: new public protected internal private
Возникает ошибка времени компиляции, если один и тот же модификатор встречается несколько раз в объявлении делегата.
Модификатор new допускается только для делегатов, объявленных в другом типе; в этом случае модификатор указывает, что такой делегат скрывает унаследованный член с тем же именем, как описано в §10.3.4.
Модификаторы public, protected, internal и private управляют доступностью типа делегата. В зависимости от контекста, в котором встречается объявление делегата, некоторые из этих модификаторов запрещены (§3.5.1).
Именем типа делегата является идентификатор.
Необязательный список_формальных_параметров определяет параметры делегата, а тип_возвращаемого_значения указывает тип возвращаемого значения делегата.
Необязательный список_параметров_типа_варианта (§13.1.3) задает параметры типа для самого делегата.
Возвращаемый тип типа делегата должен быть void или output-safe (§13.1.3.1).
Все типы формальных параметров типа делегата должны быть безопасными при вводе. Кроме того, любой из типов параметров out или ref также должен быть безопасным при выводе. Обратите внимание, что даже параметры out должны быть безопасными при вводе, согласно ограничению базовой платформы выполнения.
Типы делегатов в C# являются эквивалентом имени, а не структурным эквивалентом. А именно, два разных типа делегатов с одинаковыми списками параметров и типом возвращаемого значения считаются разными типами делегатов. Однако экземпляры двух отдельных, но структурно эквивалентных типов делегатов могут сопоставляться как равные (§7.9.8).
Пример:
delegate int D1(int i, double d);
class A { public static int M1(int a, double b) {...} }
class B { delegate int D2(int c, double d);
public static int M1(int f, double g) {...}
public static void M2(int k, double l) {...}
public static int M3(int g) {...}
public static void M4(int g) {...} }
Типы делегатов D1 и D2 оба совместимы с методами A.M1 и B.M1, так как у них одинаковый тип возвращаемого значения и список параметров; однако эти типы делегатов являются двумя разными типами, так что они не являются взаимозаменяемыми. Типы делегатов D1 и D2 несовместимы с методами B.M2, B.M3 и B.M4, так как у них разные типы возвращаемого значения или списки параметров.
Подобно другим объявлениям универсальных типов, должны быть заданы аргументы типа для создания сконструированного типа делегата. Типы параметров и тип возвращаемого значения сконструированного типа делегата создаются заменой каждого параметра типа в объявлении делегата соответствующим аргументом типа сконструированного типа делегата. Результирующие тип возвращаемого значения и типы параметров используются при определении, какие методы совместимы со сконструированным типом делегата. Пример:
delegate bool Predicate<T>(T value);
class X { static bool F(int i) {...}
static bool G(string s) {...} }
Тип делегата Predicate<int> совместим с методом X.F, а тип делегата Predicate<string> совместим с методом X.G.
Объявление_делегата — это единственный способ объявить тип делегата. Тип делегата является типом класса, производного от System.Delegate. Типы делегатов неявно sealed, поэтому никакие производные типы от типа делегата не допускаются. Недопустимо также производить тип класса не делегата от System.Delegate. Обратите внимание, что System.Delegate сам не является типом делегата; это тип класса, от которого производятся все типы делегатов.
Язык C# предоставляет специальный синтаксис для создания экземпляра и вызова делегата. За исключением создания экземпляра, любые операции, которые могут применяться к классу или экземпляру класса, могут также применяться к классу делегата или экземпляру делегата, соответственно. В частности, можно получить доступ к членам типа System.Delegate с помощью обычного синтаксиса доступа к члену.
Набор методов, инкапсулированных экземпляром делегата, называется списком вызова. Если экземпляр делегата создается (§15.2) из единственного метода, он инкапсулирует этот метод, и его список вызова содержит только одну запись. Однако, когда объединяются два непустых экземпляра делегата, их списки вызова связываются — в очередности: левый операнд, а затем правый операнд — для формирования нового списка вызова, содержащего две или более записей.
Делегаты объединяются с помощью бинарных операторов + (§7.8.4) и += (§7.17.2). Делегат можно удалить из объединения делегатов с помощью бинарных операторов - (§7.8.5) и -= (§7.17.2). Делегаты можно проверять на равенство (§7.10.8).
В следующем примере показано создание нескольких экземпляров делегата и их соответствующие списки вызова:
delegate void D(int x);
class C { public static void M1(int i) {...}
public static void M2(int i) {...}
}
class Test { static void Main() { D cd1 = new D(C.M1); // M1 D cd2 = new D(C.M2); // M2 D cd3 = cd1 + cd2; // M1 + M2 D cd4 = cd3 + cd1; // M1 + M2 + M1 D cd5 = cd4 + cd3; // M1 + M2 + M1 + M1 + M2 }
}
При создании экземпляров cd1 и cd2 каждый из них инкапсулирует один метод. При создании экземпляра cd3 его список вызова содержит два метода, M1 и M2, в этом порядке. Список вызова экземпляра cd4 содержит методы M1, M2 и M1, в этом порядке. Наконец, список вызова экземпляра cd5 содержит методы M1, M2, M1, M1 и M2, в этом порядке. Дополнительные примеры объединения (а также удаления) делегатов см. в §15.4.
