- •Спецификация языка
- •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
18.5.4Оператор адреса
Выражение_адрес состоит из амперсанда (&), за которым следует унарное_выражение.
выражение_addressof: & унарное_выражение
Если дано выражение E типа T и классифицируемое как фиксированная переменная (§18.3), конструкция &E вычисляет адрес переменной, заданной выражением E. Типом результата является T*, классифицируемый как значение. Вызывается ошибка времени компиляции, если E не классифицируется как переменная, если E классифицируется как локальная переменная только для чтения или если E обозначает перемещаемую переменную. В этом последнем случае можно использовать оператор fixed (§18.6), чтобы временно «фиксировать» переменную перед получением ее адреса. Как изложено в §7.6.4, вне конструктора экземпляров или статического конструктора для структуры или класса, определяющего поле readonly, это поле считается значением, а не переменной. Его адрес, как таковой, нельзя получить. Аналогично и адрес константы получить нельзя.
Оператор & не требует, чтобы его аргументы были определенно присвоены, но после операции & та переменная, к которой применен этот оператор, считается определенно присвоенной на пути выполнения, на котором происходит эта операция. На программиста возлагается обязанность обеспечить, чтобы правильная инициализация переменной фактически происходила в такой ситуации.
В этом примере
using System;
class Test { static void Main() { int i; unsafe { int* p = &i; *p = 123; } Console.WriteLine(i); } }
i считается определенно присвоенным после операции &i, использованной для инициализации p. Присваивание для *p в сущности инициализирует i, но включение этой инициализации является обязанностью программиста, и если удалить это присваивание, ошибки времени компиляции не будет.
Правила определенного присваивания для оператора & таковы, что можно избежать избыточной инициализации локальных переменных. Например, многие внешние API принимают указатель на структуру, заполненную посредством API. При вызове таких API обычно передается адрес локальной переменной типа структуры, и без этого правила потребовалась бы избыточная инициализация переменной типа структуры.
18.5.5Увеличение и уменьшение указателя
В небезопасном контексте операторы ++ и ‑‑ (§7.6.9 и §7.7.5) могут применяться к переменным типа указателя всех типов, кроме void*. Так, для каждого типа указателя T* неявно определены следующие операторы:
T* operator ++(T* x);
T* operator --(T* x);
Эти операторы дают такой же результат, как x + 1 и x - 1, соответственно (§18.5.6). Иначе говоря, для переменной типа указателя с типом T* оператор ++ добавляет sizeof(T) к адресу, содержащемуся в переменной, а оператор ‑‑ вычитает sizeof(T) из адреса, содержащегося в переменной.
Если при операциях увеличения или уменьшения указателя переполняется область типа указателя, результат зависит от реализации, но исключения не создаются.
18.5.6Арифметические операции с указателем
В небезопасном контексте операторы + и - (§7.8.4 и §7.8.5) могут применяться к значениям всех типов указателей, кроме void*. Так, для каждого типа указателя T* неявно определены следующие операторы:
T* operator +(T* x, int y); T* operator +(T* x, uint y); T* operator +(T* x, long y); T* operator +(T* x, ulong y);
T* operator +(int x, T* y); T* operator +(uint x, T* y); T* operator +(long x, T* y); T* operator +(ulong x, T* y);
T* operator –(T* x, int y); T* operator –(T* x, uint y); T* operator –(T* x, long y); T* operator –(T* x, ulong y);
long operator –(T* x, T* y);
Если дано выражение P типа указателя T* и выражение N типа int, uint, long или ulong, то выражения P + N и N + P вычисляют значение указателя типа T*, получающееся при добавлении N * sizeof(T) к адресу, заданному выражением P. Аналогично выражение P - N вычисляет значение указателя типа T*, получающееся при вычитании N * sizeof(T) из адреса, заданного выражением P.
Если даны два выражения, P и Q, типа указателя T*, то выражение P – Q вычисляет разность адресов, заданных P и Q, а затем делит эту разность на sizeof(T). Тип результата всегда long. В сущности, P - Q вычисляется как ((long)(P) - (long)(Q)) / sizeof(T).
Пример:
using System;
class Test {
static void Main() { unsafe { int* values = stackalloc int[20]; int* p = &values[1]; int* q = &values[15]; Console.WriteLine("p - q = {0}", p - q); Console.WriteLine("q - p = {0}", q - p); } } }
В результате получается:
p - q = -14 q - p = 14
Если при арифметических операциях с указателем переполняется область типа указателя, результат усекается способом, зависящим от реализации, но исключения не создаются.