Синтаксис C Sharp - C Sharp syntax

В этой статье описывается синтаксис из C # язык программирования. Описанные функции совместимы с .NET Framework и Мононуклеоз.

Основы

Идентификатор

An идентификатор это имя элемента в код. Есть определенный стандарт соглашения об именах следовать при выборе имен для элементов.

Идентификатор может:

  • начинаются с подчеркивания: _
  • содержать подчеркивание: _
  • содержать цифру: 0123456789
  • содержат оба верхний и нижний регистры Буквы Юникода. Дело чувствительный (FOO отличается от фу)
  • начинаются со знака @ (но это несущественно; @имя тот же идентификатор, что и имя).

Идентификатор не может:

  • начать с цифры
  • начинать с символа, если это не ключевое слово (отметьте Ключевые слова )
  • содержат более 511 символы
  • содержать знак @ после первого символа

Ключевые слова

Ключевые слова предопределенные зарезервированные слова со специальным синтаксическим значением. В языке есть два типа ключевых слов - контекстные и зарезервированные. Зарезервированные ключевые слова, такие как ложный или же байт могут использоваться только как ключевые слова. Контекстные ключевые слова, такие как куда или же из рассматриваются как ключевые слова только в определенных ситуациях.[1] Если необходим идентификатор, который будет таким же, как зарезервированное ключевое слово, он может иметь префикс @ характер, чтобы отличить его. Это облегчает повторное использование .СЕТЬ код написан на других языках.[2]

Ключевые слова C #, зарезервированные слова
Абстрактныев качествеоснованиеbool
переменак 2байтдело
ловитьcharпроверилучебный класс
constПродолжитьдесятичныйдефолт
делегироватьделатьдвойнойнисходящий 2
явныймероприятиевнешнийеще
перечислитьложныйнаконец-тофиксированный
плаватьзадля каждогоиз 2
идти кгруппа 2еслискрытый
вintинтерфейсвнутренний
в 2являетсязамокдлинный
новыйнольпространство именобъект
операторизотменятьСортировать по 2
параметрычастныйзащищенныйобщественный
только чтениессылкавозвращатьсявыключатель
структурасбайтзапечатанныйкороткая
размерstackallocстатическийнить
Выбрать 2этобросатьистинный
пытатьсятипuintУлонг
не отмеченнебезопасноushortс помощью
вар 2виртуальныйлетучийпустота
покакуда 1[3]2урожай 1 
1, 2 Это контекстные ключевые слова; таким образом (в отличие от реальных ключевых слов) можно определять переменные и типы, используя эти имена, но они действуют как ключевые слова, когда появляются в определенных позициях в коде. Контекстные ключевые слова были введены в C # 2.0, и все ключевые слова, которые будут введены в будущем языка, будут контекстными.

Использование ключевого слова в качестве идентификатора:

нить @из; // @out - это обычный идентификатор, отличный от ключевого слова out,             // который сохраняет свое особое значение

Литералы

Целые числа
десятичный23456, [0..9]+
шестнадцатеричный0xF5, 0Икс[0..9, А..F, а..ж]+
двоичный0b010110001101, 0б[0,1]+
Плавающая точка значения
плавать23,5F, 23,5f; 1.72E3F, 1.72E3f, 1.72e3F, 1.72e3f
двойной23.5, 23,5D, 23,5d; 1.72E3, 1.72E3D, ...
десятичный79228162514264337593543950335м, -0.0000000000000000000000000001м, ...
Символы
char'а', 'Z', 'u0231'
Струны
нить"Привет, мир"
"C: Windows ", @ "C: Windows" [дословные строки (которым предшествует @) могут включать символы разрыва строки и возврата каретки]
Побег персонажа в строках
Unicode персонажты за которым следует шестнадцатеричный код Unicode
Нулевой символ10
Вкладкат
Backspaceб
Возврат кареткир
Подача формыж
Обратная косая черта
Одиночная цитата'
Двойная кавычка"
Перевод строкип
1Строки в C # не оканчиваются нулем

Разделители цифр

Это особенность C # 7.0.

В подчеркивать символ разделяет цифры в числовых значениях для удобства чтения. Компилятор игнорирует эти подчеркивания.

int мусорное ведро = 0b1101_0010_1011_0100;int шестнадцатеричный = 0x2F_BB_4A_F1;int декабрь = 1_000_500_954;двойной настоящий = 1_500.200_2e-1_000;

Как правило, его можно ставить только между цифрами. Его нельзя ставить в начале (_121) или конец значения (121_ или же 121.05_), рядом с десятичной дробью в значениях с плавающей запятой (10_.0), рядом с символом экспоненты (1.1e_1) и рядом со спецификатором типа (10_f).

Переменные

Переменные - идентификаторы, связанные со значениями. Они объявляются путем записи типа и имени переменной и, возможно, инициализируются в том же операторе.

Объявить

int myInt;         // Объявление неинициализированной переменной с именем 'myInt' типа 'int'

Назначение

int myInt;        // Объявление неинициализированной переменнойmyInt = 35;       // Присваиваем переменной значение

Инициализировать

int myInt = 35;   // Объявление и инициализация переменной

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

int а, б;         // Объявление нескольких переменных одного типаint а = 2, б = 3; // Объявление и инициализация нескольких переменных одного типа

Вывод типа локальной переменной

Это особенность C # 3.0.

В C # 3.0 введен вывод типа, позволяющий заменять спецификатор типа объявления переменной ключевым словом вар, если его фактический тип можно статически определить из инициализатора. Это уменьшает повторение, особенно для типов с несколькими универсальными Тип-параметры, и более строго придерживается СУХОЙ принцип.

вар myChars = новый char[] {'А', 'Ö'}; // или char [] myChars = new char [] {'A', 'Ö'};вар myNums = новый Список<int>();  // или List  myNums = new List  ();

Смотрите также

Константы

Константы - это неизменяемые значения.

const

При объявлении локальной переменной или поля с const ключевое слово в качестве префикса, значение должно быть указано при его объявлении. После этого он заблокирован и не может быть изменен. Они могут быть объявлены в контексте как поле или локальная переменная. Константы неявно статичны.

const двойной ЧИСЛО ПИ = 3.14;

Это показывает оба использования ключевого слова.

учебный класс Фу{    const двойной Икс = 3;    Фу()    {        const int Y = 2;    }}

только чтение

В только чтение ключевое слово делает то же самое с полями. Поля, помеченные как const они не могут измениться после инициализации. Разница в том, что вы можете инициализировать их в конструкторе или значением, которое не известно до времени выполнения. Это работает только на полях. только чтение поля могут быть членами экземпляра или статическими членами класса.

Блоки кода

Фигурные скобки { ... } используются для обозначения блока кода и новой области. Члены класса и тело метода являются примерами того, что может находиться внутри этих фигурных скобок в различных контекстах.

Внутри тел методов вы можете использовать фигурные скобки для создания новых областей, например:

пустота сделай что-нибудь(){    int а;    {        int б;        а = 1;    }    а = 2;    б = 3; // Ошибка, потому что переменная объявлена ​​во внутренней области.}

Структура программы

Приложение C # состоит из классов и их членов. Классы и другие типы существуют в пространствах имен, но также могут быть вложены в другие классы.

Главный метод

Будь то консоль или приложение с графическим интерфейсом, программа должна иметь какую-то точку входа. Точкой входа в приложение C # является Главный метод. Может быть только один, и это статический метод в классе. Обычно метод возвращает пустота и ему передаются аргументы командной строки в виде массива строк.

статический пустота Главный(нить[] аргументы){}// ИЛИ Основной метод можно определить без параметров.статический пустота Главный(){}

А Главный Метод также может возвращать целочисленное значение, если указано.

статический int Главный(нить[] аргументы){    возвращаться 0;}

Пространства имён

Пространства имен являются частью имени типа и используются для группировки и / или отличия именованных сущностей от других.

Система.IO.DirectoryInfo // DirectoryInfo находится в пространстве имен System.IO

Пространство имен определяется следующим образом:

пространство имен FooNamespace{    // Члены}

с помощью директива

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

с помощью Система;с помощью System.Collections;

Директива также может использоваться для определения другого имени для существующего пространства имен или типа. Это иногда полезно, когда имена слишком длинные и плохо читаются.

с помощью Сеть = Система.Сеть;с помощью DirInfo = Система.IO.DirectoryInfo;

Операторы

Категория оператораОператоры
Арифметика+, -, *, /, %
Логический (логический и побитовый)&, |, ^, !, ~, &&, ||, истинный, ложный
Конкатенация строк+
Увеличение, уменьшение++, --
Сдвиг<<, >>
Относительный (условный)==, !=, <, >, <=, >=
Назначение=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
Доступ для членов., ?., ?[]
Индексирование[]
Бросать()
Условный (тройной)?:
Объединение и удаление делегатов+, -
Создание объектановый
Информация о типев качестве, является, размер, тип
Контроль исключений переполненияпроверил, не отмечен
Косвенное обращение и адрес*, ->, [], &
Коалесцировать??
Лямбда-выражение=>

Перегрузка оператора

Некоторые из существующих операторов можно перегрузить, написав метод перегрузки.

общественный статический Фу оператор+(Фу фу, Бар бар){    возвращаться новый Фу(фу.Ценить + бар.Ценить);}

Это перегружаемые операторы:

Операторы
+, -, !, ~, ++, --, истинный, ложныйУнарные операторы
+, -, *, /, %, &, |, ^, <<, >>Бинарные операторы
==, !=, <, >, <=, >=Операторы сравнения, необходимо перегружать попарно
  • Операторы присваивания (+=, *= и т. д.) представляют собой комбинации бинарного оператора и оператора присваивания (=) и будут оцениваться с использованием обычных операторов, которые могут быть перегружены.
  • Операторы приведения (( )) нельзя перегрузить, но вы можете определить операторы преобразования.
  • Индексирование массива ([ ]) не является перегружаемым, но вы можете определить новые индексаторы.

Смотрите также

Операторы преобразования

Оператор приведения не является перегружаемым, но вы можете написать метод оператора преобразования, который живет в целевом классе. Методы преобразования могут определять две разновидности операторов: неявные и явные операторы преобразования. Неявный оператор будет приведен без указания с помощью оператора приведения (( )), а явный оператор требует его использования.

Оператор неявного преобразования

учебный класс Фу{    общественный int Ценить;    общественный статический скрытый оператор Фу(int ценить)    {        возвращаться новый Фу(ценить);    }}// Неявное преобразованиеФу фу = 2;

Оператор явного преобразования

учебный класс Фу{    общественный int Ценить;    общественный статический явный оператор Фу(int ценить)    {        возвращаться новый Фу(ценить);    }}// Явное преобразованиеФу фу = (Фу)2;

в качестве оператор

В в качестве Оператор попытается выполнить беззвучное приведение к заданному типу. Если возможно, он вернет объект как новый тип, в противном случае вернет значение null.

Транслировать транслировать = Файл.Открыть(@ "C: Tempdata.dat");FileStream fstream = транслировать в качестве FileStream; // Вернет объект.Нить ул = транслировать в качестве Нить; // Вернет null.

Оператор Null coalesce

Это особенность C # 2.0.

Следующее:

возвращаться ifNotNullValue ?? в противном случае значение;

сокращение для:

возвращаться ifNotNullValue != ноль ? ifNotNullValue : в противном случае значение;

Это означает, что если содержимое переменной ifNotNullValue не равно нулю, это содержимое будет возвращено, иначе содержимое переменной в противном случае значение возвращается.

C # 8.0 вводит присваивание с объединением нуля, так что

Переменная ??= в противном случае значение;

эквивалентно

если (Переменная является ноль) Переменная = в противном случае значение;

Структуры управления

C # наследует большинство управляющих структур C / C ++, а также добавляет новые, такие как для каждого утверждение.

Условные структуры

Эти структуры контролируют выполнение программы в заданных условиях.

если утверждение

В если оператор вводится, когда данное условие истинно. Однострочные операторы case не требуют фигурных скобок, хотя в большинстве случаев это предпочтительнее по соглашению.

Простая однострочная инструкция:

если (я == 3) ... ;

Многострочный с блоком else (без фигурных скобок):

если (я == 2)    ...еще    ...

Рекомендуемые правила кодирования для оператора if.

если (я == 3){    ...}еще если (я == 2){    ...}еще{    ...}

выключатель утверждение

В выключатель конструкция служит фильтром для разных значений. Каждое значение приводит к «делу». Не допускается попадание в разделы дел и поэтому ключевое слово перемена обычно используется для завершения дела. Безусловный возвращаться раздел in case также может использоваться для завершения дела. Смотрите также, как идти к утверждение можно использовать для перехода от одного случая к другому. Однако во многих случаях может быть один и тот же код. Случай по умолчанию обрабатывает все остальные случаи, не обрабатываемые конструкцией.

выключатель (ch){    дело 'А':        утверждение;        ...        перемена;    дело 'B':        утверждение;        перемена;    дело 'C': // Раздел переключателя может иметь несколько меток case.    дело 'D':        ...        перемена;    дефолт:        ...        перемена;}

Итерационные структуры

Операторы итерации - это операторы, которые повторно выполняются, когда данное условие оценивается как истинное.

пока петля

пока (я == истинный){    ...}

делать ... пока петля

делать{}пока (я == истинный);

за петля

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

за (int я = 0; я < 10; я++){    ...}

Эквивалентно этому коду, представленному пока заявление, за исключением здесь я переменная не является локальной для цикла.

int я = 0;пока (я < 10){    //...    я++;}

для каждого петля

В для каждого заявление выводится из за оператор и использует определенный шаблон, описанный в спецификации языка C #, чтобы получить и использовать перечислитель элементов для итерации.

Каждый элемент в данной коллекции будет возвращен и доступен в контексте блока кода. Когда блок будет выполнен, следующий элемент будет возвращен, пока не останутся все элементы.

для каждого (int я в intList){    ...}

Заявления о прыжках

Операторы перехода наследуются от C / C ++ и, в конечном итоге, от языков ассемблера через него. Они просто представляют собой инструкции перехода на языке ассемблера, который управляет ходом выполнения программы.

Этикетки и идти к утверждение

Ярлыки представляют собой точки в коде, к которым можно перейти, используя идти к утверждение.

Начните:    .......    идти к Начните;

Обратите внимание, что этикетку не нужно размещать после идти к утверждение; он может быть перед ним в исходном файле.

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

выключатель(п){    дело 1:        Консоль.WriteLine("Случай 1");        перемена;    дело 2:        Консоль.WriteLine(«Случай 2»);        идти к дело 1;    дело 3:        Консоль.WriteLine(«Дело 3»);    дело 4: // Компиляция здесь не удастся, так как в C # случаи не могут быть выполнены.        Консоль.WriteLine(«Дело 4»);        идти к дефолт; // Это правильный способ перейти к следующему делу.    дело 5:  // Можно использовать несколько меток для одного и того же кода    дело 6:    дефолт:        Консоль.WriteLine("Дефолт");        перемена;  // Даже по умолчанию не должно доходить до конечной точки}

перемена утверждение

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

int е = 10;за (int я = 0; я < е; я++){    пока (истинный)    {        перемена;    }    // Сломаемся до этого момента.}

Продолжить утверждение

В Продолжить оператор прерывает текущую итерацию текущего оператора управления и начинает следующую итерацию.

int ch;пока ((ch = Консоль.Читать()) != -1){   	если (ch == ' ')      		Продолжить;    // Пропускает оставшуюся часть цикла while   	// Остальная часть цикла while   	...}

В пока цикл в приведенном выше коде считывает символы, вызывая GetChar(), пропуская инструкции в теле цикла, если символы являются пробелами.

Обработка исключений

Метод обработки исключений во время выполнения в C # унаследован от Java и C ++.

В библиотеке базовых классов есть класс с именем Система.Исключение от которого происходят все остальные классы исключений. An Исключение-object содержит всю информацию о конкретном исключении, а также о внутренних исключениях, которые были вызваны. Программисты могут определять свои собственные исключения, производные от Исключение учебный класс.

Исключение можно вызвать следующим образом:

    бросать новый NotImplementedException();

пытаться ... ловить ... наконец-то заявления

Исключения обрабатываются в пытаться ... ловить блоки.

пытаться{    // Заявления, которые могут вызывать исключения    ...}ловить (Исключение бывший){    // Исключение поймано и обработано здесь    ...}наконец-то{    // Операторы всегда выполняются после блоков try / catch    ...}

Заявления в пытаться блок выполняются, и если какой-либо из них вызывает исключение, выполнение блока прекращается, и исключение обрабатывается ловить блокировать. Может быть несколько ловить блоки, и в этом случае выполняется первый блок с переменной исключения, тип которой соответствует типу сгенерированного исключения.

Если нет ловить block соответствует типу сгенерированного исключения, выполнение внешнего блока (или метода), содержащего пытаться ... ловить Оператор прерывается, и исключение передается вверх и за пределы содержащего блока или метода. Исключение распространяется вверх через стек вызовов до совпадения ловить блок находится в одном из активных в настоящее время методов. Если исключение распространяется до самого верхнего Главный() метод без соответствия ловить При обнаружении блока вся программа завершается, и текстовое описание исключения записывается в стандартный поток вывода.

Заявления в наконец-то блок всегда выполняется после пытаться и ловить блоков, независимо от того, было сгенерировано исключение. Такие блоки полезны для предоставления кода очистки.

Либо ловить блок, а наконец-то блок или оба должны следовать пытаться блокировать.

Типы

C # - это статически типизированный язык, такой как C и C ++. Это означает, что каждая переменная и константа получает фиксированный тип при объявлении. Есть два типа типов: типы значений и ссылочные типы.

Типы значений

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

Структуры

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

структура Фу{    ...}

Все примитивные типы данных - это структуры.

Предопределенные типы

Это примитивные типы данных.

Примитивные типы
Введите имяBCL эквивалентЦенитьКлассифицироватьРазмерЗначение по умолчанию
сбайтСистема.SByteцелое числоОт −128 до +1278-битный (1-байтный)0
короткаяСистема.Int16целое числоОт −32,768 до +32,76716 бит (2 байта)0
intСистема.Int32целое числоОт −2 147 483 648 до +2 147 483 64732-битный (4-байтовый)0
длинныйСистема.Int64целое число−9 223 372 036 854 775 808 через
+9,223,372,036,854,775,807
64-битный (8-байтный)0
байтСистема.Байтбеззнаковое целоеОт 0 до 2558-битный (1-байтный)0
ushortСистема.UInt16беззнаковое целоеОт 0 до 65 53516 бит (2 байта)0
uintСистема.UInt32беззнаковое целоеОт 0 до 4 294 967 29532-битный (4-байтовый)0
УлонгСистема.UInt64беззнаковое целоеОт 0 до 18 446 744 073 709 551 61564-битный (8-байтный)0
десятичныйСистема.Десятичныйзнаковое десятичное число−79,228,162,514,264,337,593,543,950,335 через
+79,228,162,514,264,337,593,543,950,335
128 бит (16 байт)0.0
плаватьСистема.Одинокийчисло с плавающей запятойОт ± 1,401298E-45 до ± 3,402823E + 3832-битный (4-байтовый)0.0
двойнойСистема.Двойнойчисло с плавающей запятой± 4.94065645841246E − 324 через
± 1,79769313486232E + 308
64-битный (8-байтный)0.0
boolСистема.БулевоБулевоистинный или же ложный8-битный (1-байтный)ложный
charСистема.Charодиночный символ Unicode'u0000' через 'uFFFF'16 бит (2 байта)'u0000'

Примечание: нить (Система.Нить) не является структурой и не является примитивным типом.

Перечисления

Нумерованные типы (перечисляет) являются именованными значениями, представляющими целочисленные значения.

перечислить Время года{    Зима = 0,    Весна = 1,    Летом = 2,    Осень = 3,    Падать = Осень    // Осень в американском английском называется «Осень».}

перечислить переменные по умолчанию инициализируются нулем. Они могут быть присвоены или инициализированы именованными значениями, определенными типом перечисления.

Время года время года;время года = Время года.Весна;

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

время года = (Время года)2;  // приводим 2 к значению перечисления типа Season.время года = время года + 1; // Добавляет 1 к значению.время года = время года + сезон 2; // Добавление значений двух переменных перечисления.int ценить = (int)время года; // Преобразование enum-value в целочисленное значение.время года++; // Season.Spring (1) становится Season.Summer (2).время года--; // Season.Summer (2) становится Season.Spring (1).

Значения можно комбинировать с помощью оператора побитового ИЛИ. .

Цвет myColors = Цвет.Зеленый | Цвет.Желтый | Цвет.Синий;

Смотрите также

Типы ссылок

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

Ссылочная переменная ноль когда он не ссылается ни на один объект.

Массивы

An множество Тип - это ссылочный тип, который относится к пространству, содержащему один или несколько элементов определенного типа. Все типы массивов являются производными от общего базового класса, Система.Множество. На каждый элемент ссылается его индекс, как в C ++ и Java.

Массив в C # - это то, что можно назвать динамический массив в C ++.

int[] числа = новый int[2];числа[0] = 2;числа[1] = 5;int Икс = числа[0];
Инициализаторы

Инициализаторы массивов предоставляют удобный синтаксис для инициализации массивов.

// Длинный синтаксисint[] числа = новый int[5]{ 20, 1, 42, 15, 34 };// Краткий синтаксисint[] числа2 = { 20, 1, 42, 15, 34 };// Предполагаемый синтаксисвар числа3 = новый[] { 20, 1, 42, 15, 34 };
Многомерные массивы

Массивы могут иметь более одного измерения, например 2 измерения для представления сетки.

int[,] числа = новый int[3, 3];числа[1,2] = 2;int[,] числа2 = новый int[3, 3] { {2, 3, 2}, {1, 2, 6}, {2, 4, 5} };

Смотрите также

Классы

Классы - это определяемые пользователем ссылочные типы с самоописанием. По сути, все типы в .NET Framework - это классы, включая структуры и перечисления, которые создаются компилятором. Члены класса частный по умолчанию, но может быть объявлен как общественный быть видимым вне класса или защищенный чтобы его могли видеть все потомки класса.

Нить учебный класс

В Система.Нить класс, или просто нить, представляет собой неизменную последовательность символов Юникода (char).

Действия, выполняемые над строкой, всегда возвращают новую строку.

    нить текст = "Привет, мир!";    нить substr = текст.Подстрока(0, 5);    нить[] части = текст.Расколоть(новый char[]{ ' ' });

В Система.StringBuilder class может использоваться, когда требуется изменяемая «строка».

    StringBuilder сб = новый StringBuilder();    сб.Добавить('ЧАС');    сб.Добавить("эль");    сб.AppendLine("вот!");

Интерфейс

Интерфейсы - это структуры данных, которые содержат определения членов, но не реализуются.Переменная типа интерфейса - это ссылка на экземпляр класса, реализующего этот интерфейс. Видеть # Интерфейсы.

Делегаты

C # предоставляет типобезопасные указатели на объектно-ориентированные функции в виде делегаты.

учебный класс Программа{    // Тип делегата:    делегировать int Операция(int а, int б);    статический int Добавлять(int i1, int i2)    {        возвращаться i1 + i2;    }    статический int Sub(int i1, int i2)    {        возвращаться i1 - i2;    }    статический пустота Главный()    {        // Создаем экземпляр делегата и назначаем ему метод.        Операция op = Добавлять;        // Вызов метода, на который указывает делегат.        int результат1 = op(2, 3);  // 5        op = Sub;        int результат2 = op(10, 2); // 8    }}

Инициализация делегата анонимным методом.

  добавление = делегировать(int а, int б){ возвращаться а + б; };

Инициализация делегата лямбда-выражением.

  добавление = (а, б) => а + б;

События

События находятся указатели которые могут указывать на несколько методов. Точнее, они привязывают указатели на методы к одному идентификатору. Таким образом, это можно рассматривать как расширение делегаты. Обычно они используются в качестве триггеров при разработке пользовательского интерфейса. Форма, используемая в C # и остальные Инфраструктура общего языка основан на том, что в классике Visual Basic.

делегировать пустота MouseEventHandler(объект отправитель, MouseEventArgs е);общественный учебный класс Кнопка : Система.Windows.Управление.Контроль{    мероприятие MouseEventHandler По щелчку;    / * Мнимая функция триггера * /    пустота щелкнуть()    {        это.По щелчку(это, новый MouseEventArgs(данные));    }}

Мероприятие требует сопровождения обработчик события который создается из специального делегата, который в конкретной библиотеке платформы, например в Windows Presentation Foundation и Windows Forms обычно принимает два параметра: отправитель и аргументы события. Тип объекта-аргумента события наследуется от класса EventArgs, который является частью базовой библиотеки CLI.

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

общественный учебный класс MainWindow : Система.Windows.Управление.Окно{    частный Кнопка button1;    общественный MainWindow()    {        button1 = новый Кнопка();        button1.Текст = "Нажми на меня!";        / * Подписка на событие * /        button1.ClickEvent += button1_OnClick;        / * Альтернативный синтаксис, который считается старым:           button1.MouseClick + = новый обработчик событий MouseEventHandler (button1_OnClick); * /    }    защищенный пустота button1_OnClick(объект отправитель, MouseEventArgs е)    {        Окно сообщения.Показать("Нажал!");    }}

Также возможна реализация кастомного события:

	частный Обработчик события clickHandles = (s, е) => { };	общественный мероприятие Обработчик события Нажмите	{		Добавить		{			// Какой-то код для запуска при добавлении обработчика ...			...			clickHandles += ценить;		}		удалять		{			// Какой-то код для запуска при удалении обработчика ...			...			clickHandles -= ценить;		}	}

Смотрите также

Обнуляемые типы

Это особенность C # 2.0.

Типы, допускающие значение NULL, были впервые введены в C # 2.0, чтобы позволить типам значений быть ноль (полезно при работе с базой данных).

int? п = 2;п = ноль;Консоль.WriteLine(п.HasValue);

На самом деле это то же самое, что использовать Обнуляемый<Т> структура.

Обнуляемый<int> п = 2;п = ноль;Консоль.WriteLine(п.HasValue);

Указатели

C # имеет и позволяет указатели на выбранные типы (некоторые примитивы, перечисления, строки, указатели и даже массивы и структуры, если они содержат только типы, на которые можно указать[4]) в небезопасном контексте: методы и кодовый блок отмечены небезопасно. Синтаксически они такие же, как указатели в C и C ++. Однако проверка времени выполнения отключена внутри небезопасно блоки.

статический пустота Главный(нить[] аргументы){    небезопасно    {        int а = 2;        int* б = &а;        Консоль.WriteLine("Адрес: {0}. Значение: {1}", (int)&а, а);        Консоль.WriteLine("Адрес b: {0}. Значение: {1}. Значение * b: {2}", (int)&б, (int)б, *б);        // выведет что-то вроде:        // Адрес a: 71953600. Значение: 2        // Адрес b: 71953596. Значение: 71953600. Значение * b: 2    }}

Структуры должны быть только чистыми структурами без элементов управляемого ссылочного типа, например строка или любой другой класс.

общественный структура MyStruct{    общественный char Характер;    общественный int Целое число;}общественный структура MyContainerStruct{    общественный байт Байт;    общественный MyStruct MyStruct;}

В использовании:

MyContainerStruct Икс;MyContainerStruct* ptr = &Икс;байт ценить = ptr->Байт;

Смотрите также

Динамический

Это особенность C # 4.0 и .NET Framework 4.0.

Тип динамичный - это функция, которая позволяет статическим образом выполнять динамический поиск C # во время выполнения. Динамический обозначает переменную с объектом с типом, который разрешается во время выполнения, а не во время компиляции, как это обычно делается.

Эта функция использует преимущества Среда выполнения динамического языка (DLR) и был разработан специально с целью взаимодействия[требуется разъяснение ] с динамически типизированный языки подобно IronPython и IronRuby (Реализации Python и Рубин для .NET).

Динамическая поддержка также упрощает взаимодействие[требуется разъяснение ] с COM объекты.

динамичный Икс = новый Фу();Икс.Сделай что-нибудь();  // Компилируется и разрешается во время выполнения. Если недопустимо, будет сгенерировано исключение.

Анонимные типы

Это особенность C # 3.0.

Анонимные типы - это безымянные классы, которые генерируются компилятором. Они только расходные материалы и все же очень полезны в сценариях, например, когда у вас есть запрос LINQ, который возвращает объект на Выбрать и вы просто хотите вернуть определенные значения. Затем вы можете определить анонимный тип, содержащий автоматически сгенерированные поля только для чтения для значений.

При создании экземпляра другого объявления анонимного типа с той же сигнатурой тип автоматически определяется компилятором.

вар Карл = новый { Имя = "Карл", Возраст = 35 }; // Имя типа известно только компилятору.вар Мэри = новый { Имя = "Мэри", Возраст = 22 }; // Тот же тип, что и выражение выше

Бокс и распаковка

Заниматься боксом - это операция преобразования значения типа значения в значение соответствующего ссылочного типа.[5] Бокс в C # неявный.

Распаковка - это операция преобразования значения ссылочного типа (ранее помещенного в рамку) в значение типа значения.[5] Распаковка в C # требует явного приведения типа.

Пример:

int фу = 42;         // Тип ценности.объект бар = фу;     // foo помещается в бар.int foo2 = (int)бар;  // Распаковка обратно в тип значения.

Объектно-ориентированное программирование (ООП)

C # имеет прямую поддержку объектно-ориентированного программирования.

Объекты

Объект создается с типом в качестве шаблона и называется пример именно этого типа.

В C # объекты являются либо ссылками, либо значениями. Никаких дополнительных синтаксических различий между кодами в коде не проводится.

объект учебный класс

Все типы, даже типы значений в их упакованной форме, неявно наследуются от Система.Объект class, высший базовый класс всех объектов. Этот класс содержит наиболее общие методы, общие для всех объектов. Некоторые из них виртуальный и может быть отменено.

Классы наследуют Система.Объект прямо или косвенно через другой базовый класс.

Члены
Некоторые из членов Объект учебный класс:

  • Равно - Поддерживает сравнения между объектами.
  • Завершить - Выполняет операции очистки до того, как объект будет автоматически восстановлен. (Деструктор по умолчанию)
  • GetHashCode - Получает число, соответствующее значению объекта, для поддержки использования хеш-таблицы.
  • GetType - Получает Тип текущего экземпляра.
  • Нанизывать - Создает удобочитаемую текстовую строку, описывающую экземпляр класса. Обычно он возвращает имя типа.

Классы

Классы - это основы объектно-ориентированного языка, такого как C #. Они служат шаблоном для предметов. Они содержат элементы, которые хранят данные и манипулируют ими как в реальной жизни.

Смотрите также

Различия между классами и структурами

Хотя классы и структуры похожи как по способу объявления, так и по использованию, между ними есть некоторые существенные различия. Классы - это ссылочные типы, а структуры - это типы значений. При объявлении структура выделяется в стеке, а переменная привязана к ее адресу. Он непосредственно содержит значение. Классы разные, потому что память выделяется как объекты в куче. Переменные - это скорее управляемые указатели в стеке, указывающие на объекты. Это ссылки.

Структуры требуют больше работы, чем классы. Например, вам нужно явно создать конструктор по умолчанию, который не принимает аргументов для инициализации структуры и ее членов. Компилятор создаст для классов компилятор по умолчанию. Все поля и свойства структуры должны быть инициализированы до создания экземпляра. У структур нет финализаторов, и они не могут наследовать от другого класса, как классы. Однако они наследуют от Система.Тип ценности, который наследуется от Система.Объект. Структуры больше подходят для небольших конструкций данных.

Это краткое изложение различий:

Конструктор по умолчаниюФинализаторИнициализация членаНаследование
Классыне требуется (автогенерируемая1)дане требуетсяда (если базовый класс не запечатанный)
Структурытребуется (автогенерируемая2)неттребуетсяне поддерживается
1Генерируется только в том случае, если не указан конструктор

2Всегда автоматически генерируется и не может быть написан программистом

Декларация

Класс объявляется так:

учебный класс Фу{    // Объявления участников}
Частичный класс
Это особенность C # 2.0.

Частичный класс - это объявление класса, код которого разделен на отдельные файлы. Различные части частичного класса должны быть отмечены ключевым словом частичный.

// File1.csчастичный учебный класс Фу{    ...}// File2.csчастичный учебный класс Фу{    ...}

Инициализация

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

Фу фу = новый Фу();

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

Инициализаторы объектов
Это особенность C # 3.0.

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

Человек человек = новый Человек {    Имя = "Джон Доу",    Возраст = 39};// РавноЧеловек человек = новый Человек();человек.Имя = "Джон Доу";человек.Возраст = 39;
Инициализаторы коллекций
Это особенность C # 3.0.

Инициализаторы коллекций предоставляют синтаксис, подобный массиву, для инициализации коллекций. Компилятор просто сгенерирует вызовы метода Add. Это работает для классов, реализующих интерфейс ICollection.

Список<int> список = новый Список<int> {2, 5, 6, 6};// РавноСписок<int> список = новый Список<int>();список.Добавлять(2);список.Добавлять(5);список.Добавлять(6);список.Добавлять(6);

Доступ к участникам

Доступ к членам экземпляра и статическим членам класса осуществляется с помощью . оператор.

Доступ к члену экземпляра
Доступ к членам экземпляра можно получить через имя переменной.

нить фу = "Привет";нить fooUpper = фу.ToUpper();

Доступ к статическому члену класса
Доступ к статическим членам осуществляется с помощью имени класса или другого типа.

int р = Нить.Сравнивать(фу, fooUpper);

Доступ к члену через указатель
В небезопасный код, доступ к членам значения (типа структуры), на который ссылается указатель, осуществляется с помощью -> как в C и C ++.

ТОЧКА п;п.Икс = 2;п.Y = 6;ТОЧКА* ptr = &п;ptr->Y = 4;

Модификаторы

Модификаторы - это ключевые слова, используемые для изменения объявлений типов и членов типов. В частности, есть подгруппа, содержащая модификаторы доступа.

Модификаторы класса
  • Абстрактные - Указывает, что класс служит только базовым классом. Он должен быть реализован в наследующем классе.
  • запечатанный - Указывает, что класс не может быть унаследован.
Модификаторы членов класса
  • const - Указывает, что переменная является постоянным значением, которое должно быть инициализировано при объявлении.
  • мероприятие - Объявляет событие.
  • внешний - Указывает, что подпись метода без тела использует DLL-импорт.
  • отменять - Указывает, что объявление метода или свойства является переопределением виртуального члена или реализацией члена абстрактного класса.
  • только чтение - Объявляет поле, которому можно присвоить значения только как часть объявления или в конструкторе того же класса.
  • небезопасно - Определяет небезопасный контекст, который позволяет использовать указатели.
  • виртуальный - Указывает, что объявление метода или свойства может быть переопределено производным классом.
  • летучий - Определяет поле, которое может быть изменено внешним процессом, и предотвращает изменение использования поля оптимизирующим компилятором.
статический модификатор

В статический модификатор утверждает, что член принадлежит классу, а не конкретному объекту. Классы, отмеченные как статические, могут содержать только статические члены. Статические члены иногда называют члены класса поскольку они применяются к классу в целом, а не к его экземплярам.

общественный учебный класс Фу{    общественный статический пустота Что нибудь()    {        ...    }}// Вызов метода класса.Фу.Что нибудь();
Модификаторы доступа

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

Классы и структуры неявно внутренний и члены неявно частный если у них нет модификатора доступа.

общественный учебный класс Фу{    общественный int Делать()    {        возвращаться 0;    }    общественный учебный класс Бар    {    }}

Эта таблица определяет, где можно использовать модификаторы доступа.

Невложенные типыЧлены (включая вложенные типы)
общественныйдада
защищенный внутреннийнетда
защищенныйнетда
внутреннийда (по умолчанию)да
частный защищенныйнетда
частныйнетда (по умолчанию)

Конструкторы

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

учебный класс Фу{    Фу()    {        ...    }}

Конструкторы могут быть общественный, частный, защищенный или же внутренний.

Смотрите также

Деструктор

Деструктор вызывается, когда объект собирается сборщиком мусора для выполнения некоторой ручной очистки. Существует метод деструктора по умолчанию, называемый завершить это можно изменить, объявив собственное.

Синтаксис аналогичен синтаксису конструкторов. Разница в том, что имени предшествует ~ и оно не может содержать никаких параметров. Не может быть более одного деструктора.

учебный класс Фу{    ...    ~Фу()    {        ...    }}

Финализаторы всегда частный.

Смотрите также

Методы

Как и в C и C ++, есть функции, которые группируют повторно используемый код. Основное отличие состоит в том, что функции, как и в Java, должны находиться внутри класса. Поэтому функция называется метод. Метод имеет возвращаемое значение, имя и обычно некоторые параметры инициализируются, когда он вызывается с некоторыми аргументами. Он может принадлежать экземпляру класса или быть статическим членом.

учебный класс Фу{    int Бар(int а, int б)    {        возвращаться а%б;    }}

Метод вызывается с использованием . обозначение конкретной переменной или, как в случае статических методов, имя типа.

Фу фу = новый Фу();int р = фу.Бар(7, 2);Консоль.WriteLine(р);

Смотрите также

ссылка и из параметры

Можно явно указать аргументы, передаваемые по ссылке при вызове метода с параметрами, которым предшествуют ключевые слова. ссылка или же из. Эти управляемые указатели пригодятся при передаче переменных, которые вы хотите изменить внутри метода по ссылке. Основное различие между ними заключается в том, что из Параметр должен быть назначен в методе к моменту возврата из метода, в то время как ref не требует присвоения значения.

пустота PassRef(ссылка int Икс){    если(Икс == 2) Икс = 10;}int Z;PassRef(ссылка Z);пустота PassOut(из int Икс){    Икс = 2;}int Q;PassOut(из Q);
Необязательные параметры
Это особенность C # 4.0.

В C # 4.0 представлены необязательные параметры со значениями по умолчанию, как в C ++. Например:

пустота Приращение(ссылка int Икс, int dx = 1){  Икс += dx;}int Икс = 0;Приращение(ссылка Икс);    // dx принимает значение по умолчанию 1Приращение(ссылка Икс, 2); // dx принимает значение 2

Кроме того, чтобы дополнить необязательные параметры, можно явно указать имена параметров в вызовах методов, что позволяет выборочно передавать любое заданное подмножество необязательных параметров для метода. Единственное ограничение состоит в том, что именованные параметры должны быть помещены после безымянных параметров. Имена параметров могут быть указаны как для необязательных, так и для обязательных параметров и могут использоваться для улучшения читаемости или произвольного изменения порядка аргументов в вызове. Например:

Транслировать Открыть файл(нить имя, FileMode Режим = FileMode.Открыть,FileAccess доступ = FileAccess.Читать) { ... }Открыть файл("file.txt"); // использовать значения по умолчанию для "режима" и "доступа"Открыть файл("file.txt", Режим: FileMode.Создавать); // использовать значение по умолчанию для "доступа"Открыть файл("file.txt", доступ: FileAccess.Читать); // использовать значение по умолчанию для "режима"Открыть файл(имя: "file.txt", доступ: FileAccess.Читать, Режим: FileMode.Создавать);// называем все параметры для большей читабельности,// и используйте порядок, отличный от объявления метода

Необязательные параметры упрощают взаимодействие с COM. Раньше C # должен был передавать все параметры в методе COM-компонента, даже те, которые являются необязательными. Например:

объект имя файла = "Test.docx";объект отсутствующий = Система.Отражение.Отсутствующий.Ценить;док.Сохранить как(ссылка имя файла,    ссылка отсутствующий, ссылка отсутствующий, ссылка отсутствующий,    ссылка отсутствующий, ссылка отсутствующий, ссылка отсутствующий,    ссылка отсутствующий, ссылка отсутствующий, ссылка отсутствующий,    ссылка отсутствующий, ссылка отсутствующий, ссылка отсутствующий,    ссылка отсутствующий, ссылка отсутствующий, ссылка отсутствующий);консоль.Writeline("Файл успешно сохранен");

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

док.Сохранить как(ссылка имя файла);
внешний

Особенностью C # является возможность вызова машинного кода. Подпись метода просто объявляется без тела и помечается как внешний. В DllImport также необходимо добавить атрибут для ссылки на желаемый файл DLL.

[DllImport ("win32.dll")]статический внешний двойной Pow(двойной а, двойной б);

Поля

Поля или переменные класса могут быть объявлены внутри тела класса для хранения данных.

учебный класс Фу{    двойной фу;}

Поля могут быть инициализированы непосредственно при объявлении (если они не объявлены в структуре).

учебный класс Фу{    двойной фу = 2.3;}

Модификаторы для полей:

  • const - Делает поле постоянным.
  • частный - Делает поле приватным (по умолчанию).
  • защищенный - Делает поле защищенным.
  • общественный - Делает поле общедоступным.
  • только чтение - Позволяет инициализировать поле только один раз в конструкторе.
  • статический - Делает поле статическим членом.

Характеристики

Свойства содержат синтаксис, подобный полям, и сочетают их с мощью методов. У свойства может быть два аксессуара: получать и набор.

учебный класс Человек{    нить имя;    нить Имя    {        получать { возвращаться имя; }        набор { имя = ценить; }    }}// Использование свойстваЧеловек человек = новый Человек();человек.Имя = "Роберт";

Модификаторы свойств:

  • частный - Делает свойство частной (по умолчанию).
  • защищенный - Делает собственность защищенной.
  • общественный - Делает собственность общедоступной.
  • статический - Делает свойство статическим членом.

Модификаторы для средств доступа к свойствам:

  • частный - Делает аксессуар закрытым.
  • защищенный - Делает аксессуар защищенным.
  • общественный - Делает средство доступа общедоступным.

Модификаторы по умолчанию для средств доступа наследуются от свойства. Обратите внимание, что модификаторы средства доступа могут быть только равными или более ограничительными, чем модификатор свойства.

Автоматические свойства
Это особенность C # 3.0.

Особенностью C # 3.0 является автоматически реализуемые свойства. Вы определяете аксессоры без тел, и компилятор сгенерирует резервное поле и необходимый код для аксессоров.

общественный двойной Ширина{    получать;    частный набор;}

Индексаторы

Индексаторы добавляют к объектам возможности индексирования, подобные массиву. Они реализованы аналогично свойствам.

учебный класс IntList{   int[] Предметы;   int это[int индекс]   {        получать { возвращаться это.Предметы[индекс]; }        набор { это.Предметы[индекс] = ценить; }    }}// Использование индексатораIntList список = новый IntList();список[2] = 2;

Наследование

Классы в C # могут наследовать только от одного класса. Класс может быть производным от любого класса, не отмеченного как запечатанный.

учебный класс А{}учебный класс B : А{}

Смотрите также

виртуальный

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

Реализация выбирается фактическим типом объекта, а не типом переменной.

учебный класс Операция{    общественный виртуальный int Делать()    {        возвращаться 0;    }}учебный класс NewOperation : Операция{    общественный отменять int Делать()    {        возвращаться 1;    }}
новый

При перегрузке невиртуального метода другой сигнатурой ключевое слово новый может быть использовано. Используемый метод будет выбран по типу переменной, а не по фактическому типу объекта.

учебный класс Операция{    общественный int Делать()    {        возвращаться 0;    }}учебный класс NewOperation : Операция{    общественный новый двойной Делать()    {        возвращаться 4.0;    }}

Это демонстрирует случай:

NewOperation операция = новый NewOperation();// Будет вызывать "double Do ()" в NewOperationдвойной d = операция.Делать();Операция операция_ = операция;// Вызовет int Do () в операцииint я = операция_.Делать();
Абстрактные

Абстрактные классы - это классы, которые служат только в качестве шаблонов, и вы не можете инициализировать объект этого типа. В остальном это как обычный класс.

Также могут быть абстрактные члены. Абстрактные члены - это члены абстрактных классов, которые не имеют никакой реализации. Они должны быть переопределены классом, который наследует член.

Абстрактные учебный класс Млекопитающее{    общественный Абстрактные пустота Ходить();}учебный класс Человек : Млекопитающее{    общественный отменять пустота Ходить()    {    }    ...}
запечатанный

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

внутренний запечатанный учебный класс _FOO{}

Интерфейсы

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

интерфейс IBinaryOperation{    двойной А { получать; набор; }    двойной B { получать; набор; }    двойной GetResult();}

Реализация интерфейса

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

Неявная реализация

При неявной реализации интерфейса члены интерфейса должны быть общественный.

общественный учебный класс Сумматор : IBinaryOperation{    общественный двойной А { получать; набор; }    общественный двойной B { получать; набор; }    общественный двойной GetResult()    {        возвращаться А + B;    }}общественный учебный класс Множитель : IBinaryOperation{    общественный двойной А { получать; набор; }    общественный двойной B { получать; набор; }    общественный двойной GetResult()    {        возвращаться А*B;    }}

В использовании:

IBinaryOperation op = ноль;двойной результат;// Сумматор реализует интерфейс IBinaryOperation.op = новый Сумматор();op.А = 2;op.B = 3;результат = op.GetResult(); // 5// Multiplier также реализует интерфейс.op = новый Множитель();op.А = 5;op.B = 4;результат = op.GetResult(); // 20

Явная реализация

Вы также можете явно реализовать члены. Члены интерфейса, которые явно реализуются классом, доступны только тогда, когда объект обрабатывается как тип интерфейса.

общественный учебный класс Сумматор : IBinaryOperation{    двойной IBinaryOperation.А { получать; набор; }    двойной IBinaryOperation.B { получать; набор; }    двойной IBinaryOperation.GetResult()    {        возвращаться ((IBinaryOperation)это).А + ((IBinaryOperation)это).B;    }}

В использовании:

Сумматор Добавить = новый Сумматор();// Эти члены недоступны:// add.A = 2;// add.B = 3;// двойной результат = add.GetResult ();// Приведение к типу интерфейса для доступа к ним:IBinaryOperation add2 = Добавить;add2.А = 2;add2.B = 3;двойной результат = add2.GetResult();

Примечание: Свойства в классе, который расширяет IBinaryOperation автоматически реализуются компилятором, и автоматически добавляется поле поддержки (см. # Автоматические свойства ).

Расширение нескольких интерфейсов

Интерфейсы и классы могут расширять несколько интерфейсов.

учебный класс Мой класс : IIинтерфейсA, IIинтерфейсB{    ...}

Вот интерфейс, расширяющий два интерфейса.

интерфейс IIинтерфейсC : IIинтерфейсA, IIинтерфейсB{    ...}

Интерфейсы против абстрактных классов

Интерфейсы и абстрактные классы похожи. Ниже описаны некоторые важные различия:

  • Абстрактный класс может иметь переменные-члены, а также не абстрактные методы или свойства.Интерфейс не может.
  • Класс или абстрактный класс может наследовать только от одного класса или абстрактного класса.
  • Класс или абстрактный класс может реализовывать один или несколько интерфейсов.
  • Интерфейс может только расширять другие интерфейсы.
  • Абстрактный класс может иметь закрытые методы и свойства (также абстрактные). У интерфейса могут быть только публичные члены.
  • Абстрактный класс может иметь константы, статические методы и статические члены. Интерфейс не может.
  • У абстрактного класса могут быть конструкторы. Интерфейс не может.

Дженерики

Это особенность C # 2.0 и .NET Framework 2.0.

Дженерики (или параметризованные типы, параметрический полиморфизм ) используют параметры типа, которые позволяют разрабатывать классы и методы, не определяющие используемый тип, пока не будет создан экземпляр класса или метода. Основное преимущество заключается в том, что можно использовать параметры универсального типа для создания классов и методов, которые можно использовать без затрат на приведение типов во время выполнения или операции упаковки, как показано здесь:[6]

// Объявить универсальный класс.общественный учебный класс GenericList<Т>{    пустота Добавлять(Т Вход) { }}учебный класс TestGenericList{    частный учебный класс ExampleClass { }    статический пустота Главный()    {        // Объявить список типа int.        GenericList<int> list1 = новый GenericList<int>();        // Объявить список строкового типа.        GenericList<нить> list2 = новый GenericList<нить>();        // Объявить список типа ExampleClass.        GenericList<ExampleClass> list3 = новый GenericList<ExampleClass>();    }}

По сравнению с Шаблоны C ++ Дженерики C # могут обеспечить повышенную безопасность, но также имеют несколько ограниченные возможности.[7] Например, невозможно вызвать арифметические операторы для универсального типа C #.[8] В отличие от шаблонов C ++, параметризованные типы .NET создаются во время выполнения, а не компилятором; следовательно, они могут быть кросс-языковыми, тогда как шаблоны C ++ - нет. Они поддерживают некоторые функции, не поддерживаемые непосредственно шаблонами C ++, например ограничения типов для общих параметров с помощью интерфейсов. С другой стороны, C # не поддерживает универсальные параметры, не являющиеся типами.

В отличие от дженериков в Java, дженерики .NET используют овеществление сделать параметризованные типы первоклассными объектами в Инфраструктура общего языка (CLI) Виртуальная машина, которая позволяет оптимизировать и сохранять информацию о типе.[9]

Использование дженериков

Общие классы

Классы и структуры могут быть общими.

общественный учебный класс Список<Т>{    ...    общественный пустота Добавлять(Т элемент)    {         ...    }}Список<int> список = новый Список<int>();список.Добавлять(6);список.Добавлять(2);

Общие интерфейсы

интерфейс IEnumerable<Т>{    ...}

Общие делегаты

делегировать р Func<Т1, Т2, р>(Т1 а1, Т2 а2);

Общие методы

общественный статический Т[] CombineArrays<Т>(Т[] а, Т[] б){    Т[] newArray = новый Т[а.Длина + б.Длина];    а.Скопировать в(newArray, 0);    б.Скопировать в(newArray, а.Длина);    возвращаться newArray;}нить[] а = новый нить[] { "а", "б", "c" };нить[] б = новый нить[] { "1", "2", "3" };нить[] c = CombineArrays(а, б);двойной[] да = новый двойной[] { 1.2, 2.17, 3.141592 };двойной[] db = новый двойной[] { 4.44, 5.6, 6.02 };двойной[] Округ Колумбия = CombineArrays(да, db);// c - это массив строк, содержащий {"a", "b", "c", "1", "2", "3"}// dc - это двойной массив, содержащий {1.2, 2.17, 3.141592, 4.44, 5.6, 6.02}

Тип-параметры

Параметры типа - это имена, используемые вместо конкретных типов при определении нового универсального типа. Их можно связать с классами или методами, поместив параметр типа в угловые скобки. < >. При создании (или вызове) универсального объекта вы можете затем заменить конкретный тип параметром типа, который вы указали в его объявлении. Параметры типа могут быть ограничены с помощью куда ключевое слово и спецификацию ограничения, можно использовать любое из шести ограничений, разделенных запятыми:[10]

ОграничениеОбъяснение
куда Т : структурапараметр типа должен быть типом значения
куда Т : учебный класспараметр типа должен быть ссылочным типом
куда Т : новый()параметр типа должен иметь конструктор без параметров (должен быть последним)
куда Т : <base_class>параметр типа должен наследовать от <base_class>
куда Т : <интерфейс>параметр типа должен быть или должен реализовывать этот интерфейс
куда Т : Uограничение параметра голого типа

Ковариация и контравариантность

Это особенность C # 4.0 и .NET Framework 4.0.

Общий интерфейсы и делегаты могут иметь параметры типа, помеченные как ковариантный или же контравариантный, используя ключевые слова из и в, соответственно. Эти объявления затем учитываются при преобразовании типов, как неявном, так и явном, как во время компиляции, так и во время выполнения. Например, существующий интерфейс IEnumerable<Т> был переопределен следующим образом:

интерфейс IEnumerable<из Т>{  IEnumerator<Т> GetEnumerator();}

Следовательно, любой класс, реализующий IEnumerable<Полученный> для какого-то класса Полученный также считается совместимым с IEnumerable<Основание> для всех классов и интерфейсов Основание который Полученный расширяется, прямо или косвенно. На практике это позволяет писать такой код, как:

пустота PrintAll(IEnumerable<объект> объекты){  для каждого (объект о в объекты)  {    Система.Консоль.WriteLine(о);  }}IEnumerable<нить> струны = новый Список<нить>();PrintAll(струны); // IEnumerable  неявно преобразуется в IEnumerable 

Для контравариантности существующий интерфейс IComparer<Т> был переопределен следующим образом:

общественный интерфейс IComparer<в Т>{    int Сравнивать(Т Икс, Т у);}

Следовательно, любой класс, реализующий IComparer<Основание> для какого-то класса Основание также считается совместимым с IComparer<Полученный> для всех классов и интерфейсов Полученный которые продолжаются от Основание. Это позволяет писать такой код, как:

IComparer<объект> objectComparer = GetComparer();IComparer<нить> stringComparer = objectComparer;

Счетчики

An счетчик - итератор. Нумераторы обычно получаются путем вызова GetEnumerator() метод объекта, реализующий IEnumerable интерфейс. Классы-контейнеры обычно реализуют этот интерфейс. Тем не менее для каждого заявление в C # может работать с любым объектом, предоставляющим такой метод, даже если он не реализует IEnumerable. Этот интерфейс был расширен до общий версия в .NET 2.0.

Ниже показано простое использование итераторов в C # 2.0:

// явная версияIEnumerator<Мой тип> iter = список.GetEnumerator();пока (iter.MoveNext())    Консоль.WriteLine(iter.Текущий);// неявная версиядля каждого (Мой тип ценить в список)    Консоль.WriteLine(ценить);

Функционал генератора

Это особенность C # 2.0.

.NET 2.0 Framework позволила C # ввести итератор что обеспечивает генератор функциональность, используя урожай возвращаться строить аналогично урожай в Python.[11] С урожай возвращаться, функция автоматически сохраняет свое состояние во время итерации.

// Метод, принимающий итеративный ввод (возможно, массив)// и возвращает все четные числа.общественный статический IEnumerable<int> Получить еще(IEnumerable<int> числа){    для каждого (int я в числа)    {        если (я%2 == 0)            урожай возвращаться я;    }}// используем метод для вывода только четных чисел из массивастатический пустота Главный(){      int[] числа = { 1, 2, 3, 4, 5, 6};      для каждого (int я в Получить еще(числа))        Консоль.WriteLine(я);  // выводит 2, 4 и 6}

LINQ

Это особенность C # 3.0 и .NET Framework 3.0.

LINQ, сокращение от Language Integrated Queries, - это функция .NET Framework, которая упрощает обработку данных. В основном он добавляет поддержку, которая позволяет запрашивать массивы, коллекции и базы данных. Он также вводит связыватели, которые упрощают доступ к базам данных и их данным.

Синтаксис запроса

Синтаксис запроса LINQ был введен в C # 3.0 и позволяет писать SQL -подобные запросы в C #.

вар список = новый Список<int>{ 2, 7, 1, 3, 9 };вар результат = из я в список               куда я > 1               Выбрать я;

Операторы компилируются в вызовы методов, при этом указываются почти только имена методов. Какие методы в конечном итоге используются, определяется нормальным разрешением перегрузки. Таким образом, на конечный результат перевода влияет набор символов.

От SQL отличается то, что оператор from идет первым, а не последним, как в SQL. Это потому, что кажется более естественным писать подобное на C # и поддерживать «Intellisense» (завершение кода в редакторе).

Анонимные методы

Анонимные методы, или в их нынешней форме, чаще называемые «лямбда-выражениями», - это функция, которая позволяет вам писать в коде встроенные функции, подобные закрытию.

Есть разные способы создания анонимных методов. До C # 3.0 поддержка делегатов была ограниченной.

Смотрите также

Анонимные делегаты

Это особенность C # 2.0.

Анонимные делегаты - это указатели на функции, содержащие анонимные методы. Цель состоит в том, чтобы упростить использование делегатов за счет упрощения процесса назначения функции. Вместо объявления отдельного метода в коде программист может использовать синтаксис для написания встроенного кода, и компилятор затем сгенерирует для него анонимную функцию.

Func<int, int> ж = делегировать(int Икс) { возвращаться Икс*2; };

Лямбда-выражения

Это особенность C # 3.0.

Лямбда-выражения обеспечивают простой синтаксис для встроенных функций, похожих на замыкания. Функции с параметрами определяют тип параметров, если иное не указано явно.

// [аргументы] => [тело метода]// С параметрамип => п == 2(а, б) => а + б(а, б) => { а++; возвращаться а + б; }// С явно типизированными параметрами(int а, int б) => а + б// Без параметров() => возвращаться 0// Назначение лямбда делегатуFunc<int, int, int> ж = (а, б) => а + б;

Лямбды с несколькими операторами имеют тела, заключенные в фигурные скобки, и внутри них код может быть написан как в стандартных методах.

(а, б) => { а++; возвращаться а + б; }

Лямбда-выражения могут передаваться в качестве аргументов непосредственно в вызовах методов, аналогично анонимным делегатам, но с более эстетичным синтаксисом.

вар список = stringList.Где(п => п.Длина > 2);

Лямбда-выражения - это, по сути, методы, создаваемые компилятором, которые передаются через делегаты. Эти методы зарезервированы только для компилятора и не могут использоваться в любом другом контексте.

Методы расширения

Это особенность C # 3.0.

Методы расширения - это форма синтаксического сахара, создающая иллюзию добавления новых методов к существующему классу вне его определения. На практике метод расширения - это статический метод, который вызывается, как если бы он был методом экземпляра; получатель вызова привязан к первому параметру метода, украшенному ключевым словом это:

общественный статический учебный класс StringExtensions{    общественный статический нить Оставили(это нить s, int п)    {        возвращаться s.Подстрока(0, п);    }}нить s = "фу";s.Оставили(3); // то же, что и StringExtensions.Left (s, 3);

Смотрите также

Локальные функции

Это особенность C # 7.0.

Локальные функции могут быть определены в теле другого метода, конструктора или средства получения и установки свойства. Такие функции имеют доступ ко всем переменным в охватывающей области, включая локальные переменные родительского метода. Они входят в область действия всего метода, независимо от того, вызываются ли они до или после объявления. Модификаторы доступа (общедоступный, частный, защищенный) не могут использоваться с локальными функциями. Также они не поддерживают перегрузка функции. Это означает, что в одном методе не может быть двух локальных функций с одним и тем же именем, даже если подписи не пересекаются.[12] После компиляции локальная функция преобразуется в частный статический метод, но после определения ее нельзя пометить как статическую.[13]

В приведенном ниже примере кода метод Sum является локальной функцией внутри метода Main. Таким образом, его можно использовать только внутри родительского метода Main:

статический пустота Главный(нить[] аргументы){    int Сумма(int Икс, int у)    {        возвращаться Икс + у;    }    Консоль.WriteLine(Сумма(10, 20));    Консоль.ReadKey();}

Разное

Блоки закрытия

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

общественный пустота Фу(){    с помощью (вар бар = Файл.Открыть("Foo.txt"))    {        // поработай немного        бросать новый Исключение();        // бар все равно будет правильно расположен.    }}

Синхронизация потоков

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

частный статический StreamWriter _writer;общественный пустота ConcurrentMethod(){    замок (_writer)    {        _writer.WriteLine("Строка 1.");        _writer.WriteLine(«Далее следует строка 2».);    }}

Атрибуты

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

[CompilerGenerated]общественный учебный класс $AnonymousType$120{    [CompilerGenerated]    общественный нить Имя { получать; набор; }}

.NET Framework поставляется с предопределенными атрибутами, которые можно использовать. Некоторые из них играют важную роль во время выполнения, а некоторые предназначены только для синтаксического оформления кода, например Компилятор. Это только указывает на то, что это элемент, созданный компилятором. Также могут быть созданы атрибуты, определенные программистом.

Атрибут - это, по сути, класс, наследуемый от Система.Атрибут учебный класс. По соглашению классы атрибутов заканчиваются словом «Атрибут» в своем имени. При его использовании этого не потребуется.

общественный учебный класс EdibleAttribute : Атрибут{    общественный EdibleAttribute() : основание()    {    }    общественный EdibleAttribute(bool не ядовитый)    {        это.Ядовитый = !не ядовитый;    }    общественный bool Ядовитый { получать; набор; }}

Отображение используемого атрибута с помощью необязательных параметров конструктора.

[Съедобный (правда)]общественный учебный класс Персик : Фрукты{   // Члены, если есть}

Препроцессор

В C # есть «директивы препроцессора»[14] (хотя у него нет реального препроцессора) на основе Препроцессор C которые позволяют программистам определять символы, но не макросы. Условные выражения, такие как #если, #endif, и #еще также предоставляются.

Директивы, такие как #область, край давать подсказки редакторам для сворачивание кода. В #область, край блок должен заканчиваться #endregion директива.

общественный учебный класс Фу{    #region Constructors    общественный Фу() {}    общественный Фу(int firstParam) {}    #endregion    #region Процедуры    общественный пустота IntBar(int firstParam) {}    общественный пустота StrBar(нить firstParam) {}    общественный пустота BoolBar(bool firstParam) {}    #endregion}

Комментарии к коду

C # использует двойной слэш (//), чтобы указать, что остальная часть строки является комментарием.

общественный учебный класс Фу{    // комментарий    общественный статический пустота Бар(int firstParam) {}  // Также комментарий}

Многострочные комментарии могут быть обозначены начальной косой чертой / звездочкой (/*) и заканчивая звездочкой / косой чертой (*/).

общественный учебный класс Фу{    / * Многострочный       комментарий * /    общественный статический пустота Бар(int firstParam) {}}

Комментарии не гнездятся. Это два отдельных комментария:

// Можно положить / * * / * / * / / * / *
/ * Можно поставить / * / * / *, но оно заканчивается на * /

Однострочные комментарии, начинающиеся с трех косых черт, используются для документации XML. Однако это соглашение используется Visual Studio и не является частью определения языка:

    /// <резюме>    /// Этот класс очень классный.    /// 

Система документации XML

Система документации C # похожа на систему Java Javadoc, но на основе XML. В настоящее время C # поддерживает два метода документации. компилятор.

Однострочные комментарии к документации, такие как те, которые обычно встречаются в Visual Studio сгенерированный код, указываются в строке, начинающейся с // /.

общественный учебный класс Фу{    // /  Краткое описание метода.     // /  Описание параметра.     // /  Замечания о методе.     общественный статический пустота Бар(int firstParam) {}}

Многострочные комментарии к документации, определенные в спецификации языка версии 1.0, не поддерживались до .СЕТЬ 1.1 релиз.[15] Эти комментарии обозначаются начальной косой чертой / звездочкой / звездочкой (/**) и заканчивая звездочкой / косой чертой (*/).[16]

общественный учебный класс Фу{    / **  Краткое описание метода.      *  Описание параметра.      *  Замечания о методе.  * /    общественный статический пустота Бар(int firstParam) {}}

При использовании косой черты / звездочки / звездочки существуют некоторые строгие критерии в отношении пробелов и документации XML (/**) техника.

Этот блок кода:

/** * <резюме> * Краткое описание метода.  * /

создает другой XML-комментарий, чем этот блок кода:[16]

/** * <резюме>   Краткое описание метода.  * /

Синтаксис комментариев к документации и их XML наценка определена в ненормативном приложении к ECMA Стандарт C #. Тот же стандарт также определяет правила обработки таких комментариев и их преобразования в простой XML документ с точными правилами отображения Инфраструктура общего языка (CLI) идентификаторы к соответствующим элементам документации. Это позволяет любому C # интегрированная среда развития (IDE) или другой инструмент разработки, чтобы найти документацию для любого символа в коде определенным четко определенным способом.

Синтаксис async-await

Это особенность C # 5.0 и .NET Framework 4.0.

Начиная с .NET Framework 4 существует библиотека задач, которая упрощает написание параллельных и многопоточных приложений с помощью задач.

В C # 5.0 есть поддержка асинхронности на собственном языке.

Рассмотрим этот код, который напрямую использует преимущества библиотеки задач:

общественный статический учебный класс SomeAsyncCode{    общественный статический Задача<XDocument> GetContentAsync()    {        HttpClient httpClient = новый HttpClient();        возвращаться httpClient.GetStringAsync(«www.contoso.com»).Продолжить с((задача) => {            нить responseBodyAsText = задача.Результат;            возвращаться XDocument.Разобрать(responseBodyAsText);        });    }}вар т = SomeAsyncCode.GetContentAsync().Продолжить с((задача) => {    вар xmlDocument = задача.Результат;});т.Начинать();

Вот такая же логика, написанная в синтаксисе async-await:

общественный статический учебный класс SomeAsyncCode{    общественный статический асинхронный Задача<XDocument> GetContentAsync()    {        HttpClient httpClient = новый HttpClient();        нить responseBodyAsText = Ждите httpClient.GetStringAsync(«www.contoso.com»);        возвращаться XDocument.Разобрать(responseBodyAsText);    }}вар xmlDocument = Ждите SomeAsyncCode.GetContentAsync();// Задача будет запускаться по вызову с ожиданием.

Диалекты

Спецификация #

Spec # - это диалект C #, который разрабатывается параллельно со стандартной реализацией Microsoft. Он расширяет C # с помощью функций языка спецификаций и является возможной будущей функцией языка C #. Он также добавляет синтаксис для API контрактов кода, который был представлен в .NET Framework 4.0. Spec # разрабатывается Microsoft Research.

В этом примере показаны две основные структуры, которые используются при добавлении контрактов в ваш код.

    статический пустота Главный(нить![] аргументы)        требует аргументы.Длина > 0    {        для каждого(нить аргумент в аргументы)        {        }    }
  • ! используется, чтобы сделать ссылочный тип не допускающим значения NULL, например вы не можете установить значение на ноль. Это в отличие от типов, допускающих значение NULL, которые позволяют устанавливать типы значений как ноль.
  • требует указывает на условие, которое необходимо соблюдать в коде. В этом случае длина аргументов не может быть равна нулю или меньше.

Типы, не допускающие значения NULL

Spec # расширяет C # с помощью типов, не допускающих значения NULL, которые просто проверяют, чтобы переменные типов, допускающих значение NULL, которые были установлены как не допускающие значение NULL, не ноль. Если есть ноль тогда будет выброшено исключение.

   нить! Вход

В использовании:

   общественный Тест(нить! Вход)   {      ...   }

Предварительные условия

Предварительные условия проверяются перед выполнением метода.

   общественный Тест(int я)      требует я > 0;   {      это.я = я;   }

Постусловия

Постусловия - это условия, правильность которых гарантируется при выполнении метода.

   общественный пустота Приращение()      обеспечивает я > 0;   {      я++;   }

Проверенные исключения

Spec # добавляет проверенные исключения, подобные тем, что в Ява.

    общественный пустота Сделай что-нибудь()        бросает SomeException; // SomeException: ICheckedException    {        ...    }

Проверенные исключения проблематичны, потому что, когда функция нижнего уровня добавляет новый тип исключения, вся цепочка методов, использующих этот метод на некотором вложенном нижнем уровне, также должна изменить свой контракт. Это нарушает открытый / закрытый принцип.[17]

Смотрите также

Рекомендации

  1. ^ Шильдт, Герберт, C # 3.0: Полный справочник
  2. ^ Deitel, Harvey M .; Дейтель, Пол Дж., C # для программистов
  3. ^ Ограничения для параметров типа (Руководство по программированию на C #)
  4. ^ Типы указателей (Руководство по программированию на C #)
  5. ^ а б Лучник, Часть 2, Глава 4: Система типов
  6. ^ "Generics (Руководство по программированию на C #)". Microsoft. Получено 7 августа, 2011.
  7. ^ «Введение в универсальные шаблоны C #». Microsoft.
  8. ^ «Различия между шаблонами C ++ и универсальными шаблонами C #». Microsoft.
  9. ^ «Введение в универсальные шаблоны C #». Microsoft. Январь 2005 г.. Получено 18 июня, 2009.
  10. ^ В Microsoft MSDN: Ограничения для параметров типа (Руководство по программированию на C #)
  11. ^ "урожай". Справочник по языку C #. Microsoft. Получено 2009-04-26.
  12. ^ «.NET Framework - что нового в C # 7.0». msdn.microsoft.com. Получено 2017-04-08.
  13. ^ «Мысли о локальных функциях C # 7». Антон Сизиков. 2016-04-15. Получено 2017-04-08.
  14. ^ «Директивы препроцессора C #». Справочник по языку C #. Microsoft. Получено 18 июня, 2009.
  15. ^ Хортон, Энсон (11 сентября 2006 г.). «Вопросы и ответы по комментариям к документации по C # XML». Получено 2007-12-11.
  16. ^ а б «Разделители для тегов документации». Справочник программиста на C #. Microsoft. 1 января 1970 г.. Получено 18 июня, 2009.
  17. ^ Мартин, Роберт К. (11 августа 2008 г.), «7 Обработка ошибок, использование непроверенных исключений», Чистый код: руководство по созданию гибкого программного обеспечения, Prentice Hall International, ISBN  978-0132350884
  1. Арчер, Том (2001). Внутри C #. Microsoft Press. ISBN  0-7356-1288-9.
  2. Барт де Смет на Spec #

внешняя ссылка