Описание языка C - Новая страница 1

advertisement
Министерство образования
Российской Федерации
Нижегородский государственный университет им. Н.И. Лобачевского
Физический факультет
Кафедра информационных технологий
в физических исследованиях
Язык программирования
С#
Методическое пособие
Нижний Новгород
2005
Язык программирования
С#
Нижний Новгород
2005
УДК 681.3
Минеев С.А., Пряничников А.В., Кузьмина И.В. Язык С#. Методическое
пособие - Н.Новгород: ННГУ, 2005. - 107 с.
В пособии содержится описание семантики и синтаксиса языка
программирования общего назначения C# . Приведены описания часто
применяемых классов стандартных библиотек.
Cоставители:
Минеев С.А.- ст. преп. кафедры ИТФИ, к.ф.-м. н;
Пряничников А.В. – м.н.с НИФТИ ННГУ;
Кузьмина И.В. – м.н.с. НИФТИ ННГУ.
Рецензент:
Будников Д.Н. – инженер по программным технологиям фирмы “Intel”.
Нижегородский государственный университет
им. Н.И. Лобачевского, 2005
ВВЕДЕНИЕ
C# (читается как "Си шарп") является объектно-ориентированным языком
программирования, разработанным для создания программ на базе платформы
Microsoft .NET. Он во многом похож на другие объектно-ориентированные языки
общего назначения, такие как C++ и Java, но имеет и свои отличительные
особенности.
1. Элементы языка
1.1 Комментарии
В C# используется два типа комментирования: комментирование блока
текста, комментирование строки.
Чтобы вставить блочный (многострочный комментарий), текст комментария
обрамляется символами /* в начале и */ в конце:
/* Эта переменная хранит количество
элементов. */
int count;
Блочные
комментарии
не
могут
быть
вложенными:
последовательность символов */ завершает все открытые комментарии.
первая
Также можно закомментировать строку текста (всю или часть). Для этого
используются символы //, весь текст до конца текущей строки становится
комментарием.
int count; // Эта переменная хранит количество элементов
3
Однострочные комментарии имеют больший приоритет, т.е. символы //*
комментируют текст до конца строки, не требуя завершающих символов */.
1.2 Идентификаторы
Представляют собой последовательность букв, подчеркиваний или цифр,
начинающуюся с буквы или подчеркивания. Различают регистр, то есть foo — это
не то же самое, что Foo.
Идентификаторы могут иметь произвольную длину (однако, некоторые
реализации имеют ограничения).
Допускаются национальные символы.
4
1.3 Ключевые слова
Таб 2.1 Ключевые слова, зарезервированные языком
Abstract
class
event
if
new
readonly
As
const
explicit implicit
null
ref
Base
continue extern
in
object
return
Bool
decimal false
int
operator sbyte
Break
default
finally
interface
out
sealed
Byte
delegate fixed
internal
override short
Case
do
float
is
params
sizeof
Catch
double
for
lock
private
stackalloc
Char
else
foreach long
protected static
Checked
enum
goto
namespace public
string
struct
switch
this
throw
true
try
typeof
uint
ulong
unchecked
unsafe
ushort
using
virtual
volatile
void
while
1.4 Константы
1.4.1
Целые знаковые
Десятичные: необязательный знак, за которым следует ненулевая цифра, за
которой, в свою очередь, следует произвольное число цифр.

23, –42, 3L, +1991 // плюс допустим, но необязателен
Имеют тип int, если значение константы не превышает максимального
допустимого значения для числа типа int, в противном случае имеет тип long.
Тип для длинных целых (long) может быть явно указан с помощью постфикса
L.
1.4.2 Целые беззнаковые
Неотрицательные целые (uint) или длинные целые (ulong) константы.
Десятичные: целые или длинные целые константы без знака с постфиксом U
или u.

23U, 42u, +1991UL
Восьмеричные: ноль, за которым следует произвольное количество цифр в
диапазоне от 0 до 7.

027, 052, 03707
Шестнадцатеричные: префикс 0х или 0Х, за которым следует произвольное
количество цифр или букв в диапазоне от а до f или от А до F.
5

0х17, 0х2а, 0Х7С7
Целые беззнаковые имеют тип unsigned int, если значение константы не
превышает максимального допустимого значения для типа unsigned int, в
противном случае имеют тип unsigned long.
1.4.3 С плавающей точкой
Язык C# поддерживает два типа с плавающей точкой: float и double. Тип
float имеет точность в 7 знаков, double — 15-16.
Значения величин с плавающей точкой имеют целую часть, десятичную
точку, дробную часть, символ e или E и экспоненту со знаком или без него. Но
могут и не иметь целой или дробной части, а также не иметь десятичной точки
или экспоненты.

3.14159, 3Е8, 1.0, .2, 1.602е–19
По умолчанию значения имеют тип double, за исключением случаев, когда
они оканчиваются символом F или f (тип float).

23F, 4.2f, 1991F
// float
1.4.4 Символьные
Чаще всего представляют собой отдельный символ, заключенный в
одиночные кавычки. Имеют тип char.

'm', '7', '+'
Имеют числовые значения, которые равны значениям машинных кодов
соответствующих символов.

'А' в кодировке ASCII имеет значение 65
Для представления определенных символов используются управляющие
последовательности, начинающиеся на обратную косую черту.
Нулевой символ
Тревога (звонок)
Новая строка
Горизонтальная табуляция
Вертикальная табуляция
Забой
Возврат каретки
Прогон формата
Обратная косая черта
NULL
BEL
NL (LF)
HT
VT
BS
CR
FF
\
'\0'
'\a'
'\n'
'\t'
'\v'
'\b'
'\r'
'\f'
'\\'
6
Одиночная кавычка
Двойная кавычка
Битовая маска1
Битовая маска
‘
“
Oddd
Oxddd
'\''
'\"'
'\ddd'
'\xddd'
1.4.5 Строковые
Ноль и более символов, окруженные двойными кавычками

"m", "C++", "Частота"
Имеют тип string.
Строковые значения могут быть записаны в нескольких строках кода. Для
соединения (конкатенации) строк используется перегруженный оператор
сложения (+).

string заключение = ”Неисправны” +
“ выпускной клапан и ” +
“барометр”;

// Ниже приведены две одинаковые строки
приветствие_1 = ”Здравствуй, мир!”;
приветствие_2 = ”Здравствуй,” + “ мир!”;
1.5 Выражения
Выражения объединяют переменные, константы, вызовы функций для
получения новых значений. Например, выражениями являются следующие
операции:

i = 0;
c++;
x = a * a + b * b;
f = GetFrequency(y);
1.6 Операции
При описании операций будут использоваться следующие сокращения.
e
Произвольное выражение.
v
Любое выражение, которое может принимать значение.
i
Целое или символ.
Допускаются битовые маски, которые могут быть заданы последовательностью шестнадцатеричных или
восьмеричных цифр содержащих от одной до трех цифр.
1
7
a
Арифметическое (целое, символ или с плавающей точкой).
s
Класс.
m
Член класса.
Эти сокращения могут комбинироваться. Например, ie — это выражение
целого типа.
1.6.1 Арифметические операции
ae+ae
Сумма
ae–ae
Разность
+ae
Унарный плюс
–ae
Унарный минус
ae*ae
Произведение
ae/ae
Частное
ie%ie
Остаток от деления2
1.6.2 Логические операции
e1 & e2
И. Значение e2 вычисляется вне зависимости от значения e1.
e1 && e2 И. Значение e2 вычисляется только, если е1 истинно.
!е
НЕ (отрицание).
e1 | e2
ИЛИ. Значение e2 вычисляется вне зависимости от значения e1.
e1 || e2
ИЛИ. Значение e2 вычисляется только, если е1 ложно.
1.6.3 Операции отношения
Возвращают булево значение в соответствии с отношением своих аргументов.
==
Равно.
!=
Не равно.
<
Меньше.
<=
Меньше или равно.
>
Больше
>=
Больше или равно.
1.6.4 Операции присваивания
2
Знак результата не определен, если один из операндов или оба операнда имеют отрицательное значение.
8
v=e
Присваивает v значение е
v+=e
Эквивалентно v=v+e
v–=e
Эквивалентно v=v–e
v*=e
Эквивалентно v=v*e
v/=e
Эквивалентно v=v/e
Допускается множественное присваивание, выполняемое
операции. При этом присваивания выполняются справа налево.
в
одной
1.6.5 Операции инкремента и декремента
Операции инкремента и декремента соответственно увеличивают и
уменьшают на единицу значение переменной.
Префиксный инкремент (увеличение iv на единицу). Результатом выражения
является увеличенное на единицу значение iv.
Постфиксный инкремент (увеличение iv на единицу). Результатом является
значение iv до увеличения на единицу.
Префиксный декремент (уменьшение iv на единицу). Результатом выражения
является уменьшенное на единицу значение iv.
Постфиксный декремент (уменьшение iv на единицу). Результатом является
значение iv до уменьшения на единицу.
++iv
iv++
--iv
iv--

int a = 5, b, c;
// Постфиксный инкремент
b = a++;
// Выражение аналогично следующему:
// b = a; a++;
Console.WriteLine("a = {0}, b = {1}", a, b);
// Префиксный инкремент
c = ++b;
// Выражение аналогично следующему:
// b++; c = b;
Console.WriteLine("b = {0}, c = {1}", b, c);

Результат выполнения:
a = 6, b = 5
b = 6, c = 6
1.6.6 Операции с массивами
pe[ie]
Доступ к элементу с индексом ie массива ре.
9
1.6.7 Операции класса
Доступ к полю класса.
sv.m
1.6.8 Побитовые операции
~ie
Дополнение до единицы (побитовое НЕ).
iel << ie2
Сдвиг iel влево на ie2 бит. В освобождающиеся биты записываются нули.
iel >>ie2
iel & ie2
Сдвиг iel вправо на ie2 бит. В освобождающиеся биты записываются
нули, если iel имеет беззнаковый тип, либо неопределенное значение,
если iel имеет знаковый тип.
Побитовое И.
iel | ie2
Побитовое ИЛИ.
iel ^ ie2
Побитовое исключающее ИЛИ.

char letterA = 'A';
‘A’
char letterB = 'b';
const char mask = (char)0x20;
смены регистра
char lower = (char)(letterA |
char upper = (char)(letterB &
символ ‘B’
// Двоичное 01000001, символ
// 01100010, символ ‘ b’
// 00100000, маска для
mask);//
~mask);
01100001, символ ‘a’
// 01000010,
1.6.9 Прочие операции
el ? e2 : e3
Тернарный оператор. Если выполняется условие el, то
результатом операции является значение е2. В противном
случае результатом является значение e3.
sizeof (Тип)
Число байтов для типа Тип.
typeof (Тип)
Используется для получения объекта System.Type для типа
Тип.
as
Применяется при приведении типов.
is
Используется для проверки совместимости одного типа
данных с другим.
checked
Проверяет, не выходит ли результат арифметических
операций за пределы допустимых значений (только для
целочисленных типов).
Применяется для отмены контроля допустимых значений
вычисляемых арифметических выражений (только для
целочисленных типов).
unchecked
10
1.6.10 Операции распределения памяти
Выделяет память для типа type и возвращает ссылку на экземпляр
данного типа. При отсутствии достаточного объема памяти генерируется
исключение System.OutOfMemoryException.
new type
Выделяет память для массива из ie элементов типа type и возвращает
ссылку на массив. При этом конструктор вызывается для каждого
элемента. При отсутствии достаточного объема памяти генерируется
исключение System.OutOfMemoryException.
new type [ie]
new type [] {
Выделяет память для массива типа type и инициализирует элементы
значение_1, значениями из списка. Возвращает ссылку на массив.
значение_2,
…
}
1.6.11 Приоритет и порядок выполнения операций
В таблице, приводимой ниже, операции расположены в порядке убывания
приоритета. Операции с одинаковым приоритетом объединены в группы.
Таб.2.2
Полный набор операторов С#
Категория
Операторы
Первостепенные (первичные)
x.y, f(x), a[x], x++, x--, new, typeof, checked,
unchecked
Унарные
+, –, !, ~, ++x, --x, (T)x
Мультипликативные
*, / , %
Аддитивные
+,–
Операторы сдвига
<< , >>
Операторы отношения и проверки типов
<, >, <= , >= , is, as
Операторы равенства
==, !=
Логическое И (AND)
&
Логическое исключающее ИЛИ (XOR)
^
Логическое ИЛИ (OR)
|
Условное И (AND)
&&
Условное ИЛИ (OR)
||
Операторы проверки
?:
Операторы присваивания
=, *=, /=, %=, +=, –=, <<=, >>=, &=, ^=, |=
11
1.6.12 Арифметические преобразования
Если один из операндов имеет тип long double, double или float, то другие
операнды преобразуются к одному и тому же типу, причем long double имеет
максимальный приоритет.
Иначе, если значения типа char, unsigned char, short int, unsigned short int
могут быть представлены типом int, то все операнды указанных типов
преобразуются в int, иначе в unsigned int.
Затем, если один из операндов имеет тип unsigned long, то остальные
преобразуются в unsigned long.
Иначе, если один операнд имеет тип long int, а остальные — unsigned int, и
long int может представлять все значения unsigned int, то unsigned int
преобразуется в long int, иначе оба операнда преобразуются в тип unsigned long
int.
Иначе, если один из операндов long или int, то остальные преобразуются к
тому же типу, причем long имеет максимальный приоритет.
1.7 Операторы
1.7.1 Оператор выражения
Представляет собой выражение, заканчивающееся точкой с запятой.

Language = “C#”;
1.7.2 Оператор метки
Метка — это идентификатор, после имени которого ставится двоеточие.
Оператор метки может быть использован в операторе goto (см. п. 2.7.5.4).
1.7.3 Пустой оператор
Это просто точка с запятой. Используется, когда после метки или
операторов while, do или for не должно следовать никакого оператора.

while( !Завершено() );
1.7.4 Составной оператор
Представляет собой ноль или более операторов, заключенных в фигурные
скобки. Допустим везде, где допустим оператор выражения.

{ int t = a; a = b; b = t; }
12
1.7.5 Управляющие конструкции
Управляющие конструкции — средства, позволяющие создавать
алгоритмы. Стандартными управляющими конструкциями являются if, for,
while, goto. К тому же в C# есть несколько дополнительных конструкций:
switch, do и foreach.
1.7.5.1
if..else
Блок if..else, как следует из названия, позволяет выполнять код при
выполнении определенного условия.

if (a > b)
{
Console.WriteLine("a > b");
}
else
{
Console.WriteLine("a <= b");
}
Логическое выражение в скобках должно иметь тип bool (в отличие от
C/C++, где выражение могло быть целым или указателем). Если оно
истинно, выполнится первый блок команд, если ложно — второй. При этом
если какой-либо блок команд состоит лишь из одной команды,
обрамляющие фигурные скобки можно опустить:

1.7.5.2
if (serverObject != null)
serverObject.Initialize();
for
Цикл for представляет цикл с инициализирующей командой, условием
окончания и командой перехода.

...
double sum = 0; // сумма элементов
// Складываем все элементы массива
for (int i = 0; i<10; i++)
{
sum += array[i];
}
Логика
выполнения
цикла
следующая.
Сначала
выполняется
инициализирующая команда (в примере — int i = 0), далее идет шаг цикла:
проверяется условие окончания (i<10), если оно ложно, то цикл
13
прекращается и управление переходит на следующую за циклом команду,
иначе выполняется тело цикла, а после него — команда перехода (i++).
1.7.5.3
while
Цикл while является циклом с предусловием: сначала проверяется
определенное условие перехода, а затем выполняется итерация цикла.
int i=0;
while (i<3)
{
i++;
Console.WriteLine( i );
}

На консоль будет выведено:
1
2
3
1.7.5.4
goto
Оператор безусловного перехода goto применяется в двух ситуациях: когда
нужно перейти на обработку определенного случая в блоке switch (он будет
рассмотрен позднее, п. 2.7.5.5) или выполнить переход в определенное
место программы. Во втором случае нужно указать метку в этом месте.
Метка указывается следующим образом: в нужном месте программы
указывается имя метки с двоеточием.

Exit:
//
return 0;
Чтобы перейти
синтаксис:
goto Exit;
…

на
эту
метку,
используется
следующий
// Еще goto применяется, если нужно перейти к определенной
ветви
// в блоке switch:
int level = GetLevel();
switch (level)
{
case 0:
Console.WriteLine("Уровень 0");
break;
case 1:
goto case 2;
14
case 2:
Console.WriteLine("Уровень 2");
goto default;
default:
Console.WriteLine("Выход");
break;
}
1.7.5.5
switch
Оператор switch является расширенным оператором ветвления, который
позволяет в зависимости от значения выражения перейти к выполнению
определенного кода. По сути, он эквивалентен набору блоков if, но более
эффективен.

…
int a
= 1;
switch (a)
{
case 0:
// Операторы, выполняющиеся если a = 0
Console.WriteLine("A = 0");
break;
case 1:
// Операторы, выполняющиеся если a = 1
Console.WriteLine("A = 1");
break;
default:
// Операторы, выполняющиеся, если ни
случаев не подошел
Console.WriteLine("A <> 0 и A <> 1");
break;
}
один
из
явных
Блок case x выполняется, если выражение, указанное в скобках после switch
равно x. Блок default — если ни одно из case-выражений не выполнилось.
Удобно switch использовать для обработки выражений перечислимых
типов. Для переходов между блоками можно использовать команды goto
case и goto default. Для подробной информации смотрите описание
оператора goto.
В блоке case должно стоять константное выражение.
1.7.5.6
do
15
Оператор do реализует цикл с постусловием. Суть этого цикла аналогична
while, но условие выхода проверяется не до итерации, а после.

int i=0;
do
{
i++;
Console.WriteLine( i );
}
while (i<3);
На консоль будет выведено:
1
2
3
Обычно такой цикл применяют, когда проверку нужно выполнить после
того, как прошла хотя бы одна итерация.
1.7.5.7
foreach
foreach — оператор, облегчающий работу с коллекциями и массивами в C# .
Он позволяет перебрать все элементы некоторой коллекции или массива.
Синтаксис оператора foreach:

foreach (тип идентификатор in коллекция_или_массив)
оператор
Тип идентификатора должен соответствовать типу коллекции или массива.
Тип коллекции или массива должен реализовывать интерфейс IEnumerable
или содержать метод GetEnumerator().
По своему действию оператор foreach аналогичен следующей конструкции.

for (int i=0; i<коллекция_или_массив.Length; i++)
{
тип идентификатор = коллекция_или_массив[i];
оператор
}
Пример использования: вывод на консоль значений строкового массива.

string[]
диапазоны=new string[]{“НЧ”, “ВЧ”, “СВЧ”, “УВЧ”}
foreach (string диапазон in диапазоны)
{
диапазон=”* “+диапазон+” *”
16
Console.WriteLine(диапазон);
}
На консоль будет выведено:
*
*
*
*
НЧ *
ВЧ *
СВЧ *
УВЧ *
.
1.7.5.8
return
Если функция не объявлена как void, она должна возвращать значение. И
наоборот — функция не может возвращать значение, если она объявлена как
void. Возвращаемое значение задается инструкцией return, например:

int f1() { return 0; }
char f2() { return ‘X’; }
void f3() { return; }
Операция return прерывает выполнение функции и устанавливает
возвращаемое ей значение, для функций типа void значение не указывается.
Функция может содержать более одной инструкции return.

static int F(int a, int b)
{
return a + b;
}
static void Main()
{
int a= F(1, 2);
Console.WriteLine(a.ToString());
}
1.7.5.9
if(a==3)
return;
else
…
break
Прерывает выполнение последнего открытого оператора while, do, for,
foreach или switch.
Выполнение передается на оператор, следующий за прерванным.

static void Main(string[] args)
{
17
int i = 0;
while (true)
{
if(i == args.Length)
break;
Console.WriteLine(args[i++]);
}
}
1.7.5.10 continue
Передает управление на начало последнего открытого оператора while, do,
for или foreach.

static void Main(string[] args)
{
int i = 0;
while (true)
{
Console.WriteLine(args[i++]);
if(i < args.Length)
continue;
break;
}
}
18
2. Способы структурирования программы
2.1 Логическая организация программы
Логическая организация кода помогает лучше в нем ориентироваться,
делает код более понятным и облегчает его повторное использование. Язык C#
использует принцип построения иерархической структуры пространств имен,
принятый в .NET.
Все классы проекта могут быть распределены в соответствии с его
логической структурой по пространствам имен для образования единой
иерархии. Правильное использование пространств имен делает классы более
удобными в использовании и предотвращает конфликты с классами,
написанными другими разработчиками.
Например, стандартное пространство имен System включает в себя
пространства имен Diagnostics, Collections и другие; а Collections включает в
себя классы ArrayList, Comparer, Queue. Полные имена последних —
System.Collections.ArrayList,
System.Collections.Comparer
и
System.Collections.Queue.
Для удобства программистов в C# используется директива using,
позволяющая указывать короткие (не полные) имена классов и типов. Она
указывает, какие пространства имен используются в программе.

using System.Collections;
class Application
{
public static void Main()
{
//
Используем
класс
из
пространства
System.Collections.
ArrayList list = new ArrayList ();
…
}
}
имен
Часто бывает удобным именование членов иерархии (пространств имен)
особенным образом: например, используя название компании-разработчика.
Например, в компании HT Electronics, выполняющей работу над проектами
Web Admin и Processor Manager, классы, относящиеся к этим проектам, могут
быть расположены в пространствах имен HTElectronics.WebAdmin и
HTElectronics.ProcessorManager. Также может быть определена общая
библиотека классов в пространстве имен HTElectronics.Common.
2.2 Физическая организация программы
Под физической организацией кода понимается его размещение по файлам
и каталогам. Например, в Java существуют достаточно жесткие ограничения —
19
соответствие имен файлов именам классов, имен каталогов именам пакетов,
размещение не более одного public-класса в файле и т.д.
В C# подобных ограничений нет. Так что организация структуры файлов и
каталогов возложена на программиста. В общем случае невозможно отразить
структуру пространств имен структурой каталогов: в одном файле могут быть
объявлены классы из разных пространств имен, и наоборот — одно
пространство имен может быть представлено в нескольких файлах. Причем
отсутствие ограничений не уменьшает логичности структуры, зато часто это
удобно.
2.3 Объявления
Описывают новый тип, переменную и ее тип, константу и ее значение или
функцию, ее аргументы и возвращаемое значение.
2.3.1 Управление памятью
Единственный способ создания нового объекта в С# — использовать
ключевое слово new.
// Объекты HelloClass будут созданы при вызове метода
Main()
using System;
class HelloClass
{
public static void Main(string [] args)
{
// Новый объект можно создать в одной строке
HelloClass c1=new HelloClass();

//…или в двух
HelloClass c2;
c2 = new HelloClass();
}
}
Ключевое слово new означает, что среде выполнения следует выделить
необходимое количество оперативной памяти под экземпляр создаваемого
объекта. Выделение памяти производится из “кучи”, находящейся в
распоряжении среды выполнения .NET (managed heap — управляемой кучи).
В нашем примере объекты создаются при помощи конструктора по
умолчанию. Компилятор автоматически снабжает конструктором по
умолчанию любой класс. Если есть необходимость, вы можете переопределить
этот конструктор, заставив его выполнять нужные вам действия. Как и в С++,
конструктор класса по умолчанию — это конструктор, который не принимает
никаких параметров. Однако, если в С++ при создании объекта при помощи
конструктора по умолчанию переменные остаются неинициализированными,
20
то в С# конструктор по умолчанию (как и все другие конструкторы), если не
указано иное, присваивают всем данным состояния (например, переменным–
членам) значение по умолчанию — в большинстве случаев это 0.
Необходимо обратить внимание на то, что в программной логике метода
Main() не предусмотрено никаких средств для удаления объектов с1 и с2. В С#,
как и в Visual Basic, и в Java, программистам не надо думать о явном удалении
объектов и освобождении памяти — сборщик мусора .NET (garbage collector,
GC) освободит память автоматически. Среда выполнения удаляет объект из
памяти, когда в текущей области видимости больше не остается активных
ссылок на этот объект.

…
// Создаем локальный объект класса Газгольдер
public static int Main(string []) args)
{
// Помещаем объект класса Газгольдер в управляемую
кучу
Газгольдер
баллон_с_водородом=new
Газгольдер
(“Водород”, 200, 100)
…
return 0;
} // Если баллон_с_водородом – единственная ссылка на этот
объект,
// то с этого момента он может быть удален
2.3.2 Типы данных
Все типы в С# разделяются на две основные разновидности: структурные
типы (value-based) и ссылочные типы (reference-based). Их отличие
заключается в том, что переменные структурного типа содержат сами по себе
все данные, в то время как переменные ссылочных типов лишь ссылаются на
некоторое значение.
2.3.2.1
Структурные типы
Структурные типы делятся на несколько групп. Это могут быть
структуры, перечисления, числовые типы (которые, в свою очередь делятся на
целые, вещественные и тип decimal) и булевый тип.
2.3.2.1.1
Простые типы
Целые типы
Название Диапазон значений
типа
sbyte
–128..127
Размер
Знаковое 8-битное
целое
21
byte
0..255
char
U+0000..U+FFFF
short
–32.768..32.767
ushort
0.65535
int
–2.147.483.648..2.147.483.647
uint
0..4.294.967.295
long
–9,223,372,036,854,775,808 ..
9,223,372,036,854,775,807
0..18,446,744,073,709,551,615
ulong
Беззнаковое 8-битное
целое
16-битный Unicodeсимвол
Знаковое 16-битное
целое
Беззнаковое 16-битное
целое
Знаковое 32-битное
целое
Беззнаковое 32-битное
целое
Знаковое 64-битное
целое
Беззнаковое 64-битное
целое
Из особенностей отметим наличие 64-битных чисел и представление всех
символов как Unicode (соответственно отсутствуют знаковые/беззнаковые
символьные типы).
Типы с плавающей точкой (вещественные)
Название
типа
float
double
Примерный диапазон
значений
+1.5E–45..+3.4E38
+5.0E–324..+1.7E308
Точность
7 знаков
15–16 знаков
Тип decimal
Тип decimal описывает 128-битный числовой тип. Он может быть как
целым, так и вещественным с большой точностью, что делает его популярным
для хранения денежных сумм.
Название
типа
Decimal
2.3.2.1.2
Примерный Диапазон
значений
1.0E–28 to 7.9E28
Точность
28–39 значащих
цифр
Векторы (массивы)
Это непрерывные блоки памяти, хранящие множество элементов, одного и
того же типа. Объявляются посредством указания числа элементов, которое
должно быть положительным целым константным выражением, заключенным
в квадратные скобки []. Массивы могут быть как одномерными, так и
многомерными.

// Одномерный вектор из 10 вещественных чисел
22
float [] a = new float[10];
// Матрица из 6464 целочисленных значений
int [,] b = new int[64, 64];
// Вектор из 16 символьных векторов
char [][] c = new char [16][];
Векторы могут быть инициализированы при объявлении, например:

int [] четные_числа = new int [] {0, 2, 4, 6, 8};
Также допустима короткая форма записи (только при объявлении массива):

int [] четные_числа = {0, 2, 4, 6, 8};
int [] нечетные_числа;
нечетные_числа = {1, 3, 5, 7, 9}; // Ошибка!
При объявлении вложенных
инициализироваться отдельно.

векторов
каждый
элемент
должен
double [][] массив = new double [2][];
массив[0] = new double [3];
массив[1] = new double [4];
Возможна инициализация при объявлении:

double [][] массив = new double [2][] {
new double [3],
new double [4]
}
Работа с многомерными массивами аналогична работе с одномерными.

2.3.2.1.3
// Создание массива
int [,] двумерный_массив = new int [8, 8];
// Доступ к элементам
двумерный_массив[0, 4] = 600;
// Присваивание (новый экземпляр)
двумерный_массив = new int [,] { {0, 1}, {1, 0} };
Перечисления
Переменные типа перечисления могут принимать одно из заданных
(перечисленных) значений. Значения задаются при определении типа. Также
бывают битовые перечисления, в которых значения могут комбинироваться.
Например, определим перечисление, описывающее время года:

public enum Времена_года {Зима, Весна, Лето, Осень};
23
По умолчанию значения перечислений соответствуют целым числам,
начиная с нуля (т.е. в приведенном примере значение Времена_года.Зима
равно нулю, Времена_года.Весна — единице и т.д.), но допустимо
определение перечислений с явным указанием значений:
public enum Статус {
OK = 200,
Запрещено = 403,
Не_найдено = 404
};

2.3.2.1.4 Константы
Константы – это объекты, значение которых после инициализации не
может быть изменено (это должно быть сделано во время инициализации).

const double pi = 3.14159265358979323846;
const string warning = “Внимание!”;
2.3.2.1.5 Структуры
Структуры являются аналогом классов, но в отличие от них являются
структурным (не ссылочным) типом. То есть структуры передаются по
значению, а не по ссылке. Синтаксис для объявления структуры очень похож
на объявление класса:

public struct Point
{
public int x, y;
public Point(int p1, int p2)
{
x = p1;
y = p2;
}
}
Эта структура описывает точку на плоскости.
Для структур в С# не существует единого базового класса (тип
System.Structure в С# не определен), однако косвенно все структуры являются
производными от типа ValueType. Основное назначение ValueType
заключается в том, чтобы обеспечить типы данных, производные от
System.Object, членами для работы с этими типами данных как со
структурными (value-based), когда значения передаются как локальные копии,
а не как ссылки на области в памяти.
24
2.3.2.2
Ссылочные типы
При создании нового объекта ссылочного типа сам объект создается в
специальном пуле, а переменная представляет всего лишь ссылку на него:

class MyClass
{
...
}
…
MyClass a = new MyClass();
Если мы далее присваиваем другой переменной значение только что
созданной, для нее не создается нового объекта, она просто ссылается на
существующий:
MyClass b = a;
При этом все изменения объекта, которые производятся через b
отражаются и на a. Также значения ссылок a и b можно изменять — при этом
они перестают ссылаться на текущий объект и ссылаются на новый (или не
ссылаются ни на что — имеют значение null). Если возникает ситуация, что все
ссылки на объект изменили свои значения и на объект больше никто не
ссылается, то он становится «бесхозным» — и удаляется.
a = null;
b = null;
Прочие отличия структурных и ссылочных типов сведены в таблицу 3.1.
Таб.3.1 Отличия структурных и ссылочных типов
«Интегрирующий
Структурные типы
вопрос»
Где размещаются эти В области стека
типы?
Как
будет В виде локальной копии
представлена
типа
переменная, которой
в качестве значения
присвоен этот тип?
Что может являться Эти
типы
могут
для них базовым производится только на
типом?
прямую
от
типа
System.ValueType
Ссылочные типы
В области управляемой
кучи
В виде указателя на
область
оперативной
памяти, относящейся к
объекту этого типа
Могут производится от
любого другого типа (за
исключением
System.ValueType), если
этот тип не является
закрытым.
Может ли этот тип Нет. Структурные типы Да, если этот ссылочный
25
выступать в качестве всегда
закрыты
и
базового?
дополнение их другими
свойствами
не
предусмотрено. Поэтому
они не могут выступать
при наследовании
в
качестве базового для
других типов.
Как
производится Как значений (то есть
передача параметров? вызывающей функции
передаются
только
локальные
копии
значений переменных)
Существует
ли Нет. Структурные типы
возможность
никогда не размещаются
переопределить
в куче и поэтому к ним
Object.Finalize()?
не применяется функция
завершения.
Можно ли определить Да, но конструктор по
конструкторы
для умолчанию
этого типа?
зарезервирован (то есть
все
пользовательские
конструкторы должны
принимать параметры)
Когда
происходит Когда происходит выход
«смерть» переменной за область видимости
данного типа?
тип
не
определен
внутренне как закрытый.
Как ссылок (то есть
вызывающей функции
передается ссылка на
адрес данного объекта в
оперативной памяти)
Да, но не напрямую.
Да.
Во
время
процесса
сборки мусора (garbage
collection) в управляемой
куче
Несмотря на все различия, и структурные, и ссылочные типы могут
реализовывать стандартные (то есть встроенные) и пользовательские
интерфейсы и могут поддерживать любое количество полей, методов, свойств
и событий.
26
2.4 Классы
Одним
из
основных
понятий
объектно-ориентированного
программирования является класс. Соответственно, это понятие занимает
центральное место и в идеологии C#.
2.4.1 Объявление
Объявление класса вводит новый тип и устанавливает ограничение
доступа к членам класса. Класс объявляется с помощью ключевого слова class.

[модификаторы] class имя_класса [: базовый_класс]
{
тело класса;
}
Модификаторы доступа:
new
public
protected
internal
private
abstract
sealed
Например:

public class HelloWorldClass
{
public void HelloWorld()
{
Console.WriteLine("Здравствуй, мир!");
}
}
Класс, объявленный как public, доступен отовсюду, включая другие
сборки. Если класс объявлен как internal, он будет доступен только из текущей
сборки. Существует возможность сделать класс абстрактным:

public abstract class Баллон
{
public int Объем()
{
// Код, расположенный здесь наследуется
потомками.
…
}
27
// Данный метод необходимо определять для каждого
потомка
public abstract void Открыть();
}
Такие классы могут содержать абстрактные методы (методы, которые не
реализованы в текущем классе, но должны быть реализованы в неабстрактных
потомках). Запрещено создавать экземпляры абстрактных классов
(генерируется ошибка времени компиляции). То есть для использования
абстрактного класса, должен быть определен потомок.

public class Кислородный_баллон: Баллон
{
public override void Открыть()
{
//Здесь содержится код, выполняемый только для
// экземпляров класса Кислородный_баллон
…
}
}
Если же необходимо, чтобы у класса не было потомков, его нужно объявить
как sealed (запечатанный).

public sealed class Пульт_управления
{
…
}
…
// Это приведет к ошибке компиляции
public class Выносная_консоль: Пульт_управления
{
…
}
После двоеточия указывается класс, от которого наследуется данный. В
C# запрещено множественное наследование: класс-потомок может иметь
только один базовый класс, но он может реализовывать несколько
интерфейсов.

public class Датчик_давления
{
…
}
public class Датчик_температуры
{
…
}
28
public interface Калибратор
{
…
}
public interface Протокол
{
…
}
// Попытка наследования от нескольких классов приведет к
ошибке
// компиляции
public class Универсальный_сенсор : Датчик_давления,
Датчик_температуры,
{
…
}
// Зато можно реализовывать несколько интерфейсов
public class Прецизионный_датчик_давления:
Датчик_давления, Калибратор, Протокол
{
…
}
Если базовый класс не указан, то класс автоматически является
наследником класса System.Object (или просто object).
2.4.2 Члены класса
В теле класса объявляются его члены: поля, методы и свойства.
2.4.2.1 Поля
Поле представляет переменную, связанную с данным классом или его
экземпляром.
Модификаторы доступа:
new
public
protected
internal
private
static
readonly
volatile
29
По умолчанию: если не указан ни один модификатор доступа — поля (так
же, как методы и свойства) являются закрытыми (private).

public class MyClass
{
// Поле доступно из любого класса.
public int size;
//
Поле
доступно
только
классов-наследников
protected double coeff;
из
текущего
класса
и
// Поле доступно только внутри класса.
private string name;
// Задаем начальные значения в конструкторе
public MyClass()
{
size = 5;
coeff = 1.0;
name = “Сигнал”;
}
}
public class Application
{
public static void Main()
{
MyClass myClass = new MyClass();
// size = 5;
Console.WriteLine("size = {0}", myClass.size);
myClass.size += 5;
// size = 10
Console.WriteLine("size = {0}", myClass.size);
}
}
Также можно объявить поле как readonly — запрещается запись в поле,
кроме как посредством инициализатора или в теле конструктора.

public class MyClass
{
// Задаем начальное значение при инициализации
public readonly int size = 10;
// Задаем значение в конструкторе
public MyClass()
{
30
size = 16;
}
public SetSize()
{
size = 8; // Ошибка компиляции
}
}
Модификатор volatile запрещает некоторые оптимизации, которые могут
привести к непредсказуемым последствиям в многопоточных приложениях.
Модификатор static декларирует принадлежность члена всему классу, а не
конкретному экземпляру. Доступ к таким членам осуществляется через имя
класса, а не его экземпляра.

public class A
{
// Количество экземпляров данного класса
public static int количество_экземпляров = 0;
public A()
{
количество_экземпляров++; // Увеличиваем счетчик
экземпляров на 1
}
~A()
{
количество_экземпляров--; // Уменьшаем счетчик
экземпляров на 1
}
}
public class Б
{
public static void Main()
{
A a1=new A();
A a2=new A();
A a3=new A();
Console.WriteLine(“Количество экземпляров: {0}“,
A.количество_экземпляров);
}
}
На консоль будет выведено:
31
Количество экземпляров: 3
2.4.2.2 Методы
Методы представляют собой функции-члены: действия, которые можно
произвести с экземпляром класса или с классом (статические методы).
Модификаторы доступа:
new
public
protected
internal
private
static
virtual
sealed
override
abstract
extern

public class Пример_класса
{
private int _a;
private int _b;
public Пример_класса(int a, int b)
{
_a = a;
_b = b;
}
public int Max()
{
// Возвращаем наибольшее значение из (a, b)
return _a > _b ? _a : _b;
}
}
public class Application
{
public static void Main()
{
Пример_класса максимум = new Пример_класса (2,
10);
// MAX(2, 10) = 10
Console.WriteLine("MAX(2, 10) = {0}",
максимум.Max());
}
}
32
Модификатор static означает то же, что и в случае полей. Он указывает,
что метод принадлежит всему классу, а не конкретному экземпляру; работать
такой метод может только со статическими членами:

public class Пример_static
{
public static int _a;
public int _b;
public void Установить_b()
{
_b = _a;
}
}
public class Application
{
public static void Main()
{
Пример_static экз1 = new Пример_static(), экз2 =
new Пример_static();
Пример_static._a = 1;
экз1.Установить_b();
Пример_static._a = 2;
экз2.Установить_b();
Console.WriteLine("экз1._b = {0}, экз2._b = {1}",
экз1._b, экз2._b);
}
}
Модификатор virtual указывает, что метод может быть переопределен
(override) в потомках.
Для перегрузки методов в потомках используются модификаторы new и
override. При использовании модификатора new, метод потомка скрывает
одноименный метод родительского класса, а при использовании override метод
потомка скрывает одноименный виртуальный (virtual) метод родительского
класса.
class Базовый_класс
{
public void Метод_А()
{
Console.WriteLine("Базовый_класс.Метод_А");
}
33
public virtual void Метод_Б()
{
Console.WriteLine("Базовый_класс.Метод_Б");
}
}
class Класс_потомок : Базовый_класс
{
public new void Метод_А()
{
Console.WriteLine("Класс_потомок.Метод_А");
}
public override void Метод_Б()
{
Console.WriteLine("Класс_потомок.Метод_Б");
}
}
class Application
{
static void Main(string[] args)
{
// Создаем экземпляр Класс_потомок() и храним его в
объекте
// типа Базовый_класс.
Базовый_класс потомок = (Базовый_класс)new
Класс_потомок();
// Будет вызван метод базового класса, т.к. объект потомок
– типа
// Базовый_класс
потомок.Метод_А();
// Будет вызван метод класса-потомка, переопределенный в
классе
// Класс_потомок
потомок.Метод_Б();
}
}
Методы могут иметь параметры. Формат списка параметров следующий.

[модификатор параметра] тип_параметра имя_параметра
Существуют следующие модификаторы параметров:


out
ref
34
Модификатор out указывает, что значение параметра не передается в
метод, а возвращается из него. Реально это означает, что можно передавать
только переменную, она может быть не инициализирована и ее значение может
быть изменено в методе.
Модификатор ref указывает, что параметр передается по ссылке. То есть,
если в теле метода будет изменено его значение, изменится и значение
передаваемой переменной. С модификатором ref могут передаваться только
переменные.
Если не указан ни один из модификаторов, параметр (переменная или
константа) передается в метод; все операции над переменной сохраняются
только внутри метода.
Также существует возможность декларировать метод как принимающий
произвольное число аргументов. Для этого используется следующий
синтаксис:

params [тип элемента][] <имя списка>
Например:

class Application
{
static void Метод_с_params(string text, params
string[] args)
{
Console.WriteLine(text);
foreach(string s in args)
Console.WriteLine(s);
}
public static void Main()
{
Метод_с_params("Времена года: ",
"Весна",
"Лето",
"Осень",
"Зима");
}
}
2.4.2.3
Cвойства
Свойства расширяют возможности полей. Они представляют собой
типизированные объекты, у которых можно получить значение или записать в
35
них новое значение. При выполнении
определяемый программистом код.
этих
действий
выполняется
Модификаторы доступа к свойствам:
new
public
protected
internal
private
static
virtual
sealed
override
abstract
extern
Синтаксис для определения свойств следующий.

[модификаторы] тип имя
{
get
{
код, выполняющийся при получении значения свойства
return величина того же типа, что и свойство;
}
set
{
код, выполняющийся при установке значения свойства
переменная того же типа, что и свойство = value;
}
}
Тело get содержит код, который выполняется при получении значения
свойства. Тело set — код, который выполняется при установке нового
значения. При этом в set доступно присваиваемое значение через ключевое
слово value.

public class Пример_свойств
{
private static int _значение;
private static int _число_обращений = 0;
// Свойство – целое число с подсчетом количества
изменений значения.
public static int Значение
{
get
{
return _значение;
}
set
36
{
_число_обращений++;
_значение = value;
}
}
public static void Main()
{
Значение = 2;
Console.WriteLine("Значение = {0}", Значение);
}
}
При определении свойств класса часто возникает необходимость создать
свойство, которое будет доступно только для чтения. Делается это очень
просто: необходимо в определении свойства пропустить блок set. В результате
свойство станет доступным только для чтения.

public class Вольтметр
{
private double _напряжение;
…
// Свойство доступно только для чтения
public double Напряжение
{
get
{
// Выполняется некоторый код.
…
return _напряжение;
}
}
}
Кроме того, можно создать свойства, доступные только для записи: у них
отсутствует блок get, и имеется только блок set.
C# также поддерживает статические свойства. Обращение к статическим
свойствам производится так же, как и к статическим методам и полям.
2.4.2.4
Индексаторы
При написании приложений часто возникает необходимость создавать
объекты, представляющие коллекцию других объектов (они не обязательно
явно хранят в себе все эти объекты, но предоставляют доступ к ним). В
некоторых языках (например, Java) для этого использовались специальные
функции вроде GetItem(int index). Для упрощения синтаксиса доступа к
объектам коллекции в C# используются индексаторы (indexers). Они
37
предоставляют синтаксис, сходный с используемым при адресации массива, за
исключением того, что в качестве индекса может использоваться любой тип
данных.
Модификаторы доступа:
new
public
protected
internal
private
virtual
sealed
override
abstract
extern
Для того, чтобы объявить в классе индексатор, нужно использовать
следующий синтаксис:

[тип] this [список_параметров]
Здесь тип — это тип возвращаемого значения (т.е. тип элемента коллекции), а
список параметров — типы и имена параметров, используемых для
идентификации элемента коллекции.
Индексатор может иметь любые модификаторы, кроме static, а к
параметрам нельзя применять модификаторы out и ref.
Для определения кода индексатора нужно задать методы доступа — get
и/или set (если индексатор позволяет менять элементы). При этом в блоке get
доступны все параметры индексатора как переменные, а в методе set —
дополнительно к ним параметр value, представляющий новое значение
элемента. Таким образом, индексатор примет вид, аналогичный следующему.

…
private object GetItem(int index){…}
private void SetItem(int index, object val){…}
public object this [int index]
{
get
{
return GetItem(index);
}
set
{
SetItem(index, value);
}
}
38
2.4.2.5 Конструкторы
Конструкторы экземпляров предназначены для инициализации
вновь созданных экземпляров класса. Это специальный тип метода,
который присваивает начальные значение членам класса, производит
другие инициализирующие действия.
Важным моментом здесь является инициализация базового
класса. Для вызова конструктора базового класса используется
ключевое слово base.

class Базовый_класс
{
int _a;
public Базовый_класс(int a)
{
_a = a;
}
}
class Класс_потомок: Базовый_класс
{
// Поле _a базового класса инициализируется единицей.
public Класс_потомок (): base(1)
{
}
}
Статические конструкторы инициализируют класс в целом. Момент его
вызова неизвестен — гарантируется лишь то, что он будет вызван до создания
первого экземпляра класса. Единственное назначение статических
конструкторов — присваивать исходные значения статическим переменным.

public class АЦП
{
…
private static string _разработчик;
public static string Разработчик
{
get
{
return _разработчик;
}
}
static АЦП()
39
{
_разработчик
= ”Argusslent, Inc”;
}
…
}
public static void Main()
{
Console.WriteLine(“Производитель
АЦП.Разработчик);
}
2.4.2.6
устройства:
{0}”,
Деструкторы
Деструктор — это метод, который вызывается при уничтожении объекта.
Так как в .NET CLR используется сборщик мусора, нельзя явно удалить
определенный экземпляр. Удаление объекта происходит при первой сборке
мусора — после того, когда на экземпляр уже нет активных ссылок.
Деструкторы определяются как методы с именем, совпадающим с именем
класса, предваренным знаком ~ (тильда). Деструктор не может иметь
параметров и модификаторов; он не может быть вызван явно, т.к. его вызов
осуществляется автоматически при сборке мусора.
Несмотря на схожесть синтаксиса деструкторов в C# и деструкторов в
неуправляемом C++, они имеют совершенно различный смысл. Например, изза недетерминированности момента разрушения объектов в теле деструктора
нельзя обращаться к полям объекта (это может привести к сбою во время
исполнения): объекты-поля могут быть разрушены до объекта-оболочки, что
невозможно в неуправляемом C++.

public class A
{
~A()
{
Console.WriteLine("Объект класса А разрушен!");
}
}
public class Application
{
public static void Main()
{
A a = new A();
// Присваиваем переменной a значение null, тем
самым удаляя
// единственную активную ссылку на объект.
a = null;
// Вручную требуем произвести сбор мусора.
GC.Collect();
40
Console.WriteLine("Приложение завершено!");
}
}
Программа выведет «Объект класса А разрушен!», а затем —
«Приложение завершено!». Это означает, что сборщик мусора определил
объект, созданный оператором new как неиспользуемый, и вызвал для него
деструктор.
Инкапсуляция
2.4.3
Под инкапсуляцией понимается комбинирование данных и функций,
манипулирующих этими данными, в единый объект (класс), а также
способность классов скрывать детали реализации от пользователей. Т. е. класс
может иметь большое количество закрытых членов и методов, открытые
методы могут быть реализованы сложным образом, но пользователь класса
будет видеть только небольшое количество открытых методов, а их реализация
будет скрыта от него.
2.4.4 Наследование
Наследование — возможность создавать новые определения классов на
основе существующих. Наследование помогает пользователям расширять
возможности базового класса в производном.
При наследовании производный класс получает от базового класса все
открытые (public) и защищенные (protected) члены, то есть объект
производного класса является в полной мере объектом базового класса.
В C# для указания базового класса используется двоеточие.

class A
{
public int a;
public void Увеличить()
{
a++;
}
}
// Класс B – потомок класса A. Он наследует поле a и метод
Увеличить() базового
// класса.
class B: A
{
public void Уменьшить()
{
41
a--;
}
}
class Application
{
public static void Main()
{
B b = new B();
A a = (A)b;
a.a = 0;
// A = 0
Console.WriteLine("A = {0}", b.a);
a.Увеличить();
// A = 1
Console.WriteLine("A = {0}", b.a);
// Ошибка
// a.Уменьшить();
b.Уменьшить();
// A = 0
Console.WriteLine("A = {0}", b.a);
}
}
Для вызова конструктора базового класса при конструировании
экземпляра производного класса используется ключевое слово base.

public Формирователь_прямоугольных_импульсов(
double амплитуда,
double период,
double скважность):
base(амплитуда, период)
{
_скважность = скважность;
}
В С# множественное наследование запрещено: при создании производного
класса в качестве базового класса можно указать только один класс.
Классическое наследование — это очень удобный способ определить
набор характеристик для класса. Однако иногда встречаются ситуации, когда
необходимо запретить производить наследование от какого-либо класса. В С#
для запрещения наследования предусмотрено ключевое слово sealed.
42
// Запрещаем классу Формирователь_прямоугольных_импульсов
выступать
// в качестве базового для остальных классов.
public sealed class Формирователь_прямоугольных_импульсов:
Формирователь_сигнала
{
public Формирователь_прямоугольных_импульсов(
double амплитуда,
double период,
double скважность):
base(амплитуда, период)
{
// Код конструктора
}

// Члены класса
…
}
Поскольку класс Формирователь_прямоугольных_импульсов объявлен
как закрытый для наследования, его нельзя использовать в качестве базового
для остальных классов. Подобный код приведет к ошибке компилятора:
// Ошибка, sealed-класс не может выступать в
базового.
public class Формирователь_квадратных_импульсов:

качестве
Формирователь_прямоугольных_импульсов
{
…
}
Полиморфизм
2.4.5
Полиморфизм позволяет переопределить реакцию объекта производного
класса на метод, определенный в базовом классе. Для реализации
полиморфизма используются ключевые слова С#: virtual и override. Если
базовый класс определяет метод, который должен быть замещен в
производном классе, этот метод должен быть объявлен как виртуальный:

public class Формирователь_сигнала
{
public virtual double Мощность()
{
double мощность;
…
return мощность;
}
…
}
43
Если необходимо переопределить виртуальный метод, необходимо заново
определить этот метод в производном классе, используя ключевое слово
override.

public class Формирователь_синусоидальных_импульсов:
Формирователь_сигнала
{
public override double Мощность()
{
double коэфф;
…
return коэфф * base.Мощность();
}
…
}
В приведенном примере замещенный метод использует вызов этого же
метода базового класса. Таким образом, нет необходимости заново определять
всю логику замещенного метода в производном классе: вполне достаточно
воспользоваться вариантом метода по умолчанию, определенном в базовом
классе, дополнив его нужными действиями.
2.5 Структуры
Структуры похожи на классы тем, что они также являются набором
данных и функций для работы с этими данными. Однако, в отличие от классов,
структуры относятся к типам-значениям и не требуют размещения в куче
(heap). Переменная структурного типа содержит в себе данные структуры,
тогда как объект класса содержит ссылку на данные класса.
Структуры оказываются полезными для представления небольшого
объема данных с семантикой значений. Это, например, комплексные числа,
координаты точки на плоскости или в пространстве, пары значений в словаре и
т.д.
2.5.1 Объявление
Структура объявляется с помощью ключевого слова struct.

struct Point
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
44
Модификаторы доступа:
new
public
protected
internal
private
Модификаторы доступа структуры имеют то же смысл, что и в случае классов
(п.3.2.2).
2.5.2 Члены структуры
Структуры могу содержать любое количество внутренних членов. Членами
структур могут являться:






константы
поля
методы
свойства
индексаторы
конструкторы
2.5.3 Различия структур и классов

Структуры относятся к размерным типам, классы — к ссылочным.

Размерные типы являются производными от System.ValueType. Этот тип
имеет те же методы, что и System.Object.

Поскольку в объявлении нового размерного или ссылочного типа нельзя
указывать размерный тип в качестве базового класса, то вводить в
размерный тип новые виртуальные методы нельзя. Методы не могут быть
абстрактными и неявно являются изолированными (т.е. не могут быть
переопределены).

Экземпляры ссылочных типов размещаются в свободной памяти (в куче,
heap), а типы-значения размещаются в стеке создающего их потока. Это
существенно различающиеся по своим свойствам способы выделения
памяти.

Переменные ссылочных типов содержат адреса объектов, а переменные
типов-значений содержат сами объекты (их тела). Поэтому обращение к
полям value-типов осуществляется непосредственно, без лишней
косвенности.
45

Для ссылочных типов, и для типов-значений применяется единый
синтаксис инициализации объекта. Но, несмотря на использование
оператора new, value-типы создаются в стеке.
AClass c = new AClass();
AValue a = new AValue();
// размещается в куче
// размещается в стеке
Отличие состоит в том, что value-типы могут создаваться и без
применения оператора new. В этом случае объект value-типа создаётся
неинициализированным (под него только выделяется память), и вам
придётся его инициализировать перед первым использованием. Причем
компилятор будет следить за этим, и не позволит использовать объект до
тех пор, пока все поля не будут проинициализированы.
AValue a;
a.n = 5;
// a.s = "6";
Console.WriteLine(a); // error CS0165: Use of unassigned
local variable 'a'

На конструктор value-типа накладывается ограничение — он должен
обязательно проинициализировать все поля объекта. За этим опять будет
следить компилятор.
struct AValue
{
AValue(int n){ this.n = n; }
'Values.AValue.s' must be
// error CS0171: Field
// fully assigned before
control leaves
// the
constructor
AValue(){ this.n = 5; this.s = "6"; }
CS0568: Structs cannot contain
// explicit
parameterless constructors
public int n;
public string s;
// остался не
проинициализированным
}
// error

Ещё одно ограничение — конструктор обязательно должен иметь
параметры. Для типов-значений нельзя задать свой конструктор по
умолчанию (без параметров). По законам .Net используемый по
умолчанию конструктор value-типа должен всегда инициализировать все
поля нулями (0 или null).

У типов-значений не бывает деструкторов.
46

Объекты ссылочных типов передаются как параметры методов по ссылке,
а объекты типов-значений по значению. Это означает, что в случае
ссылочного типа копируется сама ссылка (указатель), а при передаче типазначения копируются все его поля. Если структура состоит из одного-двух
полей небольшого размера, передача ее в качестве параметра происходит
даже быстрее, чем передача ссылки на объект, так как отсутствуют
дополнительные операторы взятия и разрешения ссылки. Но при больших
размерах структуры эффективность ее передачи в качестве параметра
резко снижается. Увеличить производительность передачи структуры
можно, объявив параметр как ссылку с ключевым словом ref. Но при этом
исходное содержимое структуры может быть изменено внутри
вызываемого метода.
2.6 Массивы
Массив — это набор однотипных значений, рассматриваемый как единое
целое.
2.6.1 Типы массива
Общеязыковая исполняющая среда Microsoft .Net (CLR) поддерживает
массивы:
 одномерные (single-dimensional);
 многомерные (multidimensional);
 вложенные (jagged).
Базовым для всех массивов является тип System.Array, производный от
System.Object. Массивы всегда относятся к ссылочному типу и размещаются в
управляемой куче, а переменные содержат не сам массив, а ссылку на него.
2.6.2 Объявление массива

// Одномерные массивы:
int [] array = new int[10];
int [] array = new int[]{1, 2, 3, 4, 5};
Доступ к элементам производится с помощью оператора [], элементы
нумеруются индексами от 0 до (N – 1), где N — размер массива.
int element = array[0];

// Многомерные массивы:
int [,] array = new int[10, 20];
int [,] array = {{1, 2}, {3, 4}};
47
Доступ к элементам производится с помощью оператора [], в котором индексы
также указываются через запятую. Элементы нумеруются наборами индексов,
каждый из которых может принимать значение от 0 до (N – 1), где N — размер
соответствующего измерения массива.
int element = array[0, 2];

Вложенные массивы:
int [][] array = new int[2][];
array[0] = new int[4];
array[1] = new int[20];
Доступ:
int element = array[0][1];
2.6.3 Члены массива
У типа System.Array есть несколько статических и экземплярных членов.
Поскольку все массивы являются неявно производными от System.Array, эти
члены можно использовать для работы с массивами и размерных и ссылочных
типов.
2.7 Интерфейсы
Интерфейсы предоставляют средство обобщения классов, от которых
требуются однотипная реакция на определенные вызовы. Список вызовов, на
которые должен реагировать класс (эти вызовы могут быть представлены в
форме вызовов методов, изменении значений свойств и индексаторов,
генерации событий) собираются в интерфейсе. Интерфейсы никогда не
являются типами данных, и в них не бывает реализации методов по
умолчанию. Каждый член интерфейса (свойство или метод) автоматически
становится абстрактным.
Интерфейсы могут содержать в себе свойства, методы, индексаторы и
события, но не могут содержать их реализации. Они лишь декларируют, какие
члены должны содержать классы и структуры, реализующие данный
интерфейс.
2.7.1 Объявление
С точки зрения синтаксиса интерфейсы в С# определяются следующим
образом.
[модификаторы] interface имя_интерфейса: [базовые интерфейсы]
{
[Свойства интерфейса]
48
[Методы интерфейса]
[Индексаторы интерфейса]
[События интерфейса]
}
Из модификаторов доступа разрешены new, public, protected, internal и private.
// Этот интерфейс определяет работу с многогранниками
public interface IPolyhedron
{
…
int GetNumberOfEdges();
…
}
2.7.2 Члены интерфейса
Интерфейс может содержать любое количество членов. Членами
интерфейса могут быть методы, свойства, события, или индексаторы. С# не
допускает определения статических членов
интерфейса. Кроме того,
интерфейс не может иметь экземплярные поля и конструкторы.
Например, рассмотрим интерфейс, который содержит каждый из
возможных видов членов: метод, свойство, событие, и индексатор.

public delegate void StringListEvent(IStringList sender);
public interface IstringList
{
// Метод
void Add(string s);
// Свойство – только для чтения
int Count { get; }
// Событие
event StringListEvent Changed;
// Индексатор, предоставляющий доступ как для чтения,
так и для записи
string this[int index] { get; set; }
}
Интерфейс — это просто абстрактный тип, состоящий из набора
виртуальных методов, каждый из которых имеет свое имя, параметры и
возвращаемый тип. Методы интерфейса не могут иметь реализации, так что
они являются незавершенными (абстрактными).
Интерфейсы .NET могут поддерживать любое количество свойств.

public interface IPolyhedron
49
{
int NumberOfEdges { get; set; }
}
Чтобы определить свойство только для чтения или только для записи
достаточно просто не указать соответствующий блок (set или get).
2.7.3 Реализация интерфейса
Когда в C# какой-либо класс должен реализовать нужные пользователь
интерфейсы, названия этих интерфейсов должны быть помещены (через
запятую) после двоеточия, следующего за именем этого класса.

interface ICloneable
{
object Clone();
}
interface IComparable
{
int CompareTo(object other);
}
class ListEntry: ICloneable, IComparable
{
public object Clone() {...}
public int CompareTo(object other) {...}
}
В классе обязательно должны быть реализованы все методы данного
интерфейса.
2.7.4 Наследование
В C# два интерфейса могут вступать между собой в отношения
наследования, при которых один интерфейс станет базовым, а другой —
производным. Базовый интерфейс определяет общее поведение, в то время как
производный интерфейс — более конкретное и специфическое.

// Базовый интерфейс
interface IDraw
{
void Draw();
}
interface IDraw2 : IDraw
{
void DrawToPrinter();
}
interface IDraw3 : IDraw2
50
{
void DrawToMetafile();
}
Если реализуемый класс должен поддерживать поведение, определенное
во всех трех интерфейсах, он должен производиться от интерфейса самого
верхнего уровня (в нашем случае – IDraw3). Все методы, определенные в
базовых интерфейсах, будут автоматически включены в производные
интерфейсы.

// Этот класс будет поддерживать IDraw, IDraw2, IDraw3
public class SuperImage : IDraw3
{
// Используем явную реализацию интерфейсов, чтобы
привязать методы
// к конкретным интерфейсам
void IDraw.IDraw()
{
// Обычный вывод на экран
}
void IDraw2.IDrawToPrinter()
{
// Вывод на принтер
}
void IDraw3. IDrawToMetafile()
{
// Вывод в метафайл
}
}
В С# допускается наследование сразу от нескольких базовых интерфейсов
(в отличие от классов).
Предположим, что в распоряжении пользователя есть набор интерфейсов,
моделирующих поведение автомобиля:

interface IBasicCar
{
void Drive();
}
interface IUnderWaterCar
{
void Dive();
}
// А это интерфейс, производный сразу от двух предыдущих:
interface IJamesBondCar : IBasicCar, IUnderWaterCar
{
void TurboBoost();
51
}
Если необходимо создать класс, который реализует интерфейс
IJamesBondCar, нам придется реализовать в нем все методы каждого из
интерфейсов.
public class JBСar : IJamesBondCar
{
public JBCar() {}
// Унаследованные члены
void IBasicCar.Drive() { Console.WriteLine(“Ускорение…”) }
void IUnderWaterCar () { Console.WriteLine(“Погружение…”)}
void IJamesBondCar () { Console.WriteLine(“Отрыв!”) }
}
2.8 Перегрузка операций
В дополнение к стандартным интерпретациям унарных и бинарных
операторов в C# есть возможность для классов и структур переопределить их
значение. Для этого используется ключевое слово operator. Обратите
внимание, что его можно использовать только вместе с ключевым словом
static.
Можно перегружать следующие операторы: унарные +, –, !, ~, ++, --, true,
false и бинарные +, –, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, <=, к тому же при
перегрузке бинарных операторов перегружается и соответствующие оператор
присваивания: например для + автоматически перегружается +=.
2.8.1 Унарные операции
При перегрузке унарных операторов используется синтаксис

operator символ оператора ( параметр )
2.8.2 Бинарные операции
При перегрузке бинарных операторов используется синтаксис

operator символ оператора ( оператор 1, оператор 2 )
Например:
public struct Vector
{
private double x, y;
public Vector( double x, double y )
52
{
this.x = x;
this.y = y;
}
// Перегружаем оператор сложения
public static Vector operator + ( Vector a, Vector b )
{
return new Vector(a.x + b.x, a.y + b.y);
}
public override string ToString()
{
return "[" + x + ", " + y + "]";
}
}
public class Application
{
public static void Main()
{
Vector a = new Vector(1, 2);
Vector b = new Vector(2, 3);
Vector c = a + b;
Console.WriteLine("{0} + {1} = {2}", a, b, c);
}
}
Необходимо отметить, что не все операторы можно перегрузить.
Информация о перегружаемости операторов представлена в следующей
таблице:
Таб. 3.2Возможность перегрузки операторов в С#
Оператор С#
+, –, !, ~, ++, --,
true, false
+, –, *, /, %, &,
|, ^, <<, >>
==, !=, <, >,
<=,>=
[]
Можно ли произвести перегрузку
Любой оператор из этого набора унарных операторов может
быть перегружен
Любой оператор из этого набора бинарных операторов
может быть перегружен
Все эти операторы сравнения могут быть перегружены
Этот оператор не может быть перегружен. Однако можно
применять его к конкретному классу, если в нем реализован
метод индексатора
53
2.9 Делегаты
В платформе .NET, и соответственно в C#, реализована концепция
делегатов — объектно-ориентированного подобия указателей на функции в
C++. При помощи делегатов поддерживается механизм функций обратного
вызова. В отличие от механизмов обратного вызова из других платформ, таких
как С++, функциональность делегатов намного богаче. Например, делегаты
обеспечивают безопасность типов при исполнении метода обратного вызова.
Делегаты также поддерживают последовательный вызов нескольких методов и
позволяют вызывать как статические, так и экземплярные методы.
2.9.1 Объявление
Объявление делегатов имеет следующий синтаксис.
[модификаторы] delegate тип идентификатор
([параметры]);

Допустимы следующие модификаторы:
new
public
protected
internal
private
Объявление делегата создает класс, а не просто указатель на метод,
именно поэтому не нарушаются объектно-ориентированные концепции.
Делегат может существовать отдельно от логически связанного с ним
класса, а может быть помещен непосредственно внутрь определения класса,
тогда он будет вложенным классом.
Например:

delegate int D(int i, double d);
class A
{
public static int M(int a, double b) {...}
}
class B
{
delegate int D(int c, double d);
public static int M(int f, double g) {...}
}
Существует два типа делегатов — одиночные (Singlecast) и
комбинированные (Multicast). С точки зрения синтаксиса объявления они
различаются только типом возвращаемого значения. При описании одиночных
54
делегатов создается класс, наследующий System.Delegate, а при описании
комбинированных — наследующий System.MulticastDelegate.
2.9.2 Одиночные делегаты
Пример использования одиночного делегата.

using System;
public delegate int SingleDelegate(int x);
public class SampleDelegateClass
{
int sampleMethod(int x)
{
// …
Console.WriteLine(x);
return 0;
}
public static void Main(String[] args)
{
// Создаем экземпляр этого класса
SampleDelegateClass sdc = new
SampleDelegateClass();
//Создаем экземпляр делегата
SingleDelegate sDelegate = new
SingleDelegate(sdc.sampleMethod);
Console.WriteLine(sDelegate(255));
}
}
2.9.3 Комбинированные делегаты
По своей структуре комбинированные делегаты — это связный список
делегатов с возвращаемым типом void. Вообще любой делегат, с
возвращаемым типом void является комбинированным, даже если представляет
связный список с одним элементом. Комбинированные делегаты наследуются
от System.MulticastDelegate.
Комбинированные делегаты могут соединяться с помощью статического
метода Combine класса System.Delegate:
public static Delegate Combine(Delegate[]);
//
комбинирует массив делегатов
public static Delegate Combine(Delegate, Delegate); //
комбинирует два делегата
55
Для удаления делегата из связного списка существует статический метод
Remove класса System.Delegate:
public static Delegate Remove(Delegate source, Delegate
value);
где source — связный список делегатов, value — удаляемый
делегат.
Комбинирование и удаление делегата также можно осуществлять с
помощью перегруженных операторов += и –= соответственно.
Приведем пример использования комбинированных делегатов.

using System;
public delegate void sampleDelegate(int x);
public class DelegateClass1
{
public void sampleMethod(int x)
{
Console.WriteLine(x – 2);
}
}
public class DelegateClass2
{
public void sampleMethod(int x)
{
Console.WriteLine(x + 2);
}
}
public class UseDelegates
{
public static void Main(String[] args)
{
DelegateClass1 dc1 = new DelegateClass1();
DelegateClass2 dc2 = new DelegateClass2();
// Создаем экземпляры делегатов
sampleDelegate sDelegate1 = new
sampleDelegate(dc1.sampleMethod);
sampleDelegate sDelegate2 = new
sampleDelegate(dc2.sampleMethod);
sampleDelegate sdCombination;
// Создаем комбинированный делегат
sdCombination =
(sampleDelegate)Delegate.Combine(sDelegate1, sDelegate2);
56
sdCombination(3);
}
}
Здесь вызовы sDelegate1 и sDelegate2 объединяются в sdCombination, а
затем вызывается полученная комбинация. Получить массив делегатов,
скомбинированных в один делегат sdCombination можно с помощью метода
GetInvocationList().
Delegate[] sDelegates;
sDelegates = sdCombination.GetInvocationList();
2.9.4 Использование делегатов
Делегаты могут использоваться для вызова как статических, так и
нестатических функций. Например:
delegate void D(int x);
class C
{
public static void M1(int i) {...}
public void M2(int i) {...}
}
class Application
{
static void Main()
{
D cd1 = new D(C.M1);
C test = new C();
D cd2 = new D(test.M2);
метод
}
}
// статический метод
// нестатический
Вызов делегатов, указывающих на нестатические функции, производится
через объект класса.
57
2.10 События
Наиболее логичным применением делегатов является обработка событий.
Если в типе определен член-событие, то этот тип или (его экземпляр)
может уведомлять другие объекты о некоторых особых событиях. Например,
класс Button (“кнопка”) определяет событие Click (“щелчок”). В приложении
могут быть объекты, которые должны получать уведомление о щелчке объекта
Button, и, получив такое уведомление, исполнять некоторые действия.
События — это члены типа, обеспечивающие такого рода взаимодействие.
2.10.1 Объявление
События объявляются с помощью ключевого слова event.
public
delegate
System.EventArgs e);

void
EventHandler(object
sender,
public class Button
{
public event EventHandler Click;
public void Reset()
{
Click = null;
}
}
2.10.2 Генерация событий
Функциональные
возможности
события
представлены
тремя
взаимодействующими
элементами:
класс,
который
предоставляет
дополнительную информацию, передаваемую получателям уведомления о
событии, делегат события, и класс, который генерирует событие. Чтобы
вызвать событие по имени EventName, необходимо создать следующие
элементы.
1.
2.
3.
Класс,
который
содержит
данные
события,
именованный
EventNameEventArgs.
Этот
класс
должен
происходить
от
System.EventArgs.
Делегат, определяющий прототип метода, который будет вызван при
срабатывании события. Согласно принятым правилам имя делегата
должно заканчиваться словом EventHandler, а сам он должен иметь
возвращаемое значение типа void и принимать два параметра:
 object — ссылка на объект, присылающий уведомление;
 тип, производный от EventArgs, содержащий любую дополнительную
информацию, необходимую получателям уведомления.
Событие.
58
4.
5.
Защищенный виртуальный метод, ответственный за уведомление
зарегистрированных объектов о событии.
Метод, транслирующий входную информацию в желаемое событие
Для подписки на события используется оператор +=, для её отмены —
оператор –=.

using System;
public class SampleForm
{
private Button SampleButton;
public SampleForm ()
{
SampleButton = new Button();
SampleButton.Click += new
EventHandler(SampleButton_Click);
}
void SampleButton_Click(object sender, EventArgs e)
{
Console.WriteLine("Кнопка нажата!");
}
public void Disconnect()
{
SampleButton.Click –= new
EventHandler(SampleButton_Click);
}
}
2.11 Атрибуты
Атрибуты позволяют добавлять любую дополнительную текстовую
информацию о ваших классах, методах, полях, свойствах и т.д. Атрибуты
сохраняются вместе с метаданными (metadata) и могут быть достаточно просто
получены во время выполнения программы при помощи процесса называемого
reflection.
2.11.1 Типы данных допустимые в атрибутах
Атрибут может содержать поля следующих типов:








bool
byte
char
double
float
int
long
short
59





string
object
System.Type
открытые перечислимые типы
одномерные массивы из перечисленных выше типов
Попытка использовать в классе, реализующем атрибут, другие типы
приводит к ошибкам компиляции.
2.11.2 Объявление
Атрибутивные классы должны объявляться как открытые.
По соглашению имена классов должны заканчиваться словом Attribute.
Хотя это и необязательно, рекомендуется поступать так для улучшения
читаемости текста. При использовании атрибута это слово
необязательно.
Все атрибутивные классы должны наследоватьcя от System.Attribute.
Атрибутивные классы должны иметь атрибут AttributeUsageAttribute,
обозначающий область применения (языковые элементы). Если атрибут
не указан, используется значение по умолчанию (п. 3.9.8).




Например:

// Этот атрибут может применяться только к методам
[AttributeUsage(AttributeTargets.Method)]
public class MethodsAttribute: System.Attribute
{
// ...
}
2.11.3 Конструктор
Атрибуты инициализируются конструкторами, так же как обычные
классы. Следующий фрагмент кода иллюстрирует типичный конструктор
атрибута. Этот открытый конструктор принимает один параметр и
инициализирует переменную класса.

public SampleAttribute(bool bool_value)
{
this.bool_value = bool_value;
}
Конструкторы можно перегружать, чтобы принимать различные
комбинации параметров. Если для атрибутивного класса определены свойства,
для инициализации можно использовать комбинацию позиционных и
именованных параметров. Обычно все обязательные параметры объявляются
как позиционные, а необязательные как именованные.
60
Примеры использования параметризованного конструктора для
инициализации атрибута (предполагается, что атрибут имеет обязательный
параметр типа Boolean и необязательный типа String).
// Один обязательный (позиционный) и один необязательный
(именованный)
// параметры.
[SampleAttribute(false, OptionalParameter =
"дополнительные данные")]


// Один обязательный (позиционный) параметр.
[SampleAttribute(false)]
Параметры, определенные как свойства, могут передаваться в
произвольном порядке. Но обязательные параметры должны передаваться в
том порядке, в котором они описаны в конструкторе. Следующий фрагмент
кода показывает, как необязательный параметр может передаваться перед
обязательным.

// Именованный параметр помещается перед позиционным.
[MyAttribute(OptionalParameter = "дополнительные данные",
false)]
2.11.4 Свойства
Свойства определяются, если нужно передавать именованные параметры в
конструкторы или легко и удобно получать значения полей атрибута.
Следующий пример показывает, как реализовать простое свойство для
пользовательского атрибута:

public bool BoolProperty
{
get { return this.bool_value; }
set { this.bool_value = value; }
}
2.11.5 Применение атрибутов
Большинство атрибутов применяется к таким элементам языка как классы,
методы, поля и свойства. Но некоторые атрибуты являются глобальными —
они воздействуют на всю сборку или модуль. Глобальные атрибуты в текстах
программ объявляются после using-директив верхнего уровня перед
определениями типов и пространств имен. Они могут использоваться в разных
исходных файлах одной программы.
2.11.5.1 Применение атрибутов на уровне классов и методов
61
Атрибуты в программном коде используются следующим образом:
1. Определяется новый или берется существующий в .NET Framework
атрибут.
2. Инициализируется конкретный экземпляр атрибута с помощью вызова
конструктора атрибута.
Атрибут помещается в метаданные при компиляции кода и становится
доступен CLR и любым инструментальным средствам и приложениям через
механизмы рефлексии.
По соглашению имена всех атрибутов оканчиваются словом Attribute.
Однако, язык C#, не требуют задания полного имени атрибута. Например, если
нужно инициализировать атрибут System.ObsoleteAttribute, достаточно
написать Obsolete.
Следующий
пример
показывает,
как
использовать
атрибут
System.ObsoleteAttribute, помечающий код как устаревший. Атрибуту
передается строка «Будет удалено в следующей версии». Этот атрибут
заставляет компилятор выдать переданную строку как предупреждение при
попытке использования помеченного кода.

using System;
public class Application
{
public static void Main()
{
// На этой строке компилятор выдаст
предупреждение.
int i = Add(2, 2);
}
// Этот атрибут применяется только к методу Add.
[Obsolete("В следующей версии метод будет удален")]
public static int Add(int a, int b)
{
return (a + b);
}
}
2.11.5.2 Применение атрибутов на уровне сборок
Для применения атрибутов на уровне сборок используется идентификатор
assembly. Следующий пример показывает, как используется атрибут
AssemblyNameAttribute:

using System.Reflection;
[assembly: AssemblyName("Драйвер_устройства")]
62
2.11.5.3 Применение атрибутов на уровне модулей
Для применения атрибутов на
идентификатор module вместо assembly.
уровне
модулей
используется
2.11.6 Специализированные атрибуты
В разных пространствах имен .NET определено множество готовых к
использованию атрибутов. Многие из них предназначены для организации
взаимодействия COM/.NET, отладки и других аспектов в создании
приложений .NET. Несколько встроенных атрибутов представлено в
следующей таблице:
Таб. 3.3
Атрибут
Встроенные атрибуты
Назначение
CLSCompliant Определяет совместимость всех типов сборки с Common
Language Specification (CLS). Является эквивалентом атрибута
[oleautomation] в IDL.
DllImport
Для вызова традиционных файлов dll в операционной
системе.
StructLayout
Для определения внутреннего представления структуры.
DispID
Определяет DISPID для члена в интерфейсе COM.
Serializable
Помечает класс или структуру как сериализуемые (например,
доступные для сохранения на диске и восстановления с него).
Помечает поля сериализуемых классов или структур как
несериализуемые.
NonSerialized
К примеру, атрибут DllImport используется, чтобы указать, что метод
класса импортируется из Dll.

using System.Runtime.InteropServices;
public class AppMain
{
[DllImport("user32.dll")]
public static extern int MessageBoxA(int handle, string
message, string caption, int flags);
public static void Main()
{
MessageBoxA(0, "Hello World!", "Native Message Box",
0);
63
}
}
CLR позволяет применять атрибуты практически ко всему, что может
быть представлено метаданными. Чаще всего атрибуты применяются к
элементам таблиц определений TypeDef (классы, структуры, перечисления,
интерфейсы и делегаты), MethodDef (конструкторы), ParamDef, FieldDef,
PropertyDef, EventDef, AssemblyDef и ModuleDef. Реже атрибуты применяются
к ссылочным таблицам AssemblyDef, ModuleDef, TypeDef и MemberDef. Кроме
того, специализированные атрибуты могут применяться к таким элементам
метаданных, как права доступа, экспортируемые типы и ресурсы.
С# позволяет задавать префикс, указывающий сущность, к которой
применяется атрибут.

// Возможные префиксы:
[assembly:
MyAttribute(1)]
// Применяется к сборке
[module: MyAttribute(2)]
// Применяется к модулю
[type:
MyAttribute(3)]
// Применяется к типу
class SomeType
{
[property: MyAttribute(4)]
//
Применяется
свойству
public String SomeProp { get { return null; } }
к
[event:
MyAttribute(5)]
// Применяется к событию
public event EventHandler SomeEvent;
[field:
MyAttribute(6)]
public Int32 SomeField = 0;
// Применяется к полю
[return:
MyAttribute(7)]
//
Применяется
к
возвращаемому значению
[method:
MyAttribute(8)]
// Применяется к методу
public Int32 SomeMethod(
[param: MyAttribute(9)] // Применяется к параметру
Int32 SomeParam) { return SomeParam; }
}
При применении нескольких атрибутов к одной сущности порядок
атрибутов не имеет значения. В С# каждый атрибут может быть заключен в
квадратные скобки, или несколько атрибутов, разделенных запятыми,
перечисляются в одних квадратных скобках. Необязательными являются
суффикс Attribute и круглые скобки, если конструктор типа не имеет
параметров.

Возможные способы применения атрибутов:
[Serializable][Flags]
64
[Serializable, Flags]
[FlagsAttribute, SerializableAttribute]
[FlagsAttribute()][Serializable()]
2.11.7 Определение собственного атрибута
В этом разделе объединяется вся предыдущая информация и
показывается, как создать простой атрибут, документирующий некоторый
фрагмент кода. Атрибут из этого примера содержит информацию об имени и
уровне программиста, а также о времени последнего пересмотра кода. Он
содержит три закрытых переменных, в которых хранятся данные. Каждая
переменная связана с открытым свойством для чтения и записи значений.
Также имеется конструктор с двумя обязательными параметрами.

[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : System.Attribute
{
// Закрытые поля.
private string name;
private string level;
private bool reviewed;
// Конструктор принимает два обязательных параметра:
имя и уровень.
public DeveloperAttribute(string name, string level)
{
this.name = name;
this.level = level;
this.reviewed = false;
}
// Свойство Name.
// Только для чтения.
public virtual string Name
{
get { return name; }
}
// Свойство Level.
// Только для чтения.
public virtual string Level
{
get { return level; }
}
// Свойство Reviewed.
// Чтение / Запись.
public virtual bool Reviewed
{
get { return reviewed; }
set { reviewed = value; }
65
}
}
При создании атрибута в C# необходим предопределенный атрибут —
AttributeUsage.(3.9.8) Он задает элементы кода, к которым применим атрибут
(в данном случае методы), а также некоторые свойства атрибута. Например,
может ли быть атрибут примененным несколько раз к одному элементу.
Применять этот атрибут можно, используя как полное имя
DeveloperAttribute, так и сокращенное — Developer.

[Developer("Василий Пупкин", "1")]
[Developer("Василий Пупкин", "1", Reviewed = true)]
2.11.8 Использование атрибута AttributeUsageAttribute
Атрибут AttributeUsageAttribute позволяет указать компилятору, где
допускается применение вашего специализированного атрибута.
У типа AttributeUsageAttribute есть конструктор, позволяющий передавать
параметры:

один или несколько, приведенных ниже, элементов перечисления
AttributeTarget;

именованный аргумент AllowMultiple (необязательный), который
определяет, может ли этот аргумент применяться к одному и тому же типу
несколько раз;

параметр Inherited типа bool (необязательный), определяет должен ли
этот атрибут наследоваться производными классами.

namespace System
{
[AttributeUsage(AttributeTargets.Class)]
public class AttributeUsageAttribute: Attribute
{
public AttributeUsageAttribute(AttributeTargets
validOn) {...}
public virtual bool AllowMultiple { get {...} set
{...} }
public virtual bool Inherited { get {...} set
{...} }
public virtual AttributeTargets ValidOn { get
{...} }
}
public enum AttributeTargets
{
Assembly
= 0x0001,
Module
= 0x0002,
Class
= 0x0004,
Struct
= 0x0008,
Enum
= 0x0010,
66
Constructor = 0x0020,
Method
= 0x0040,
Property
= 0x0080,
Field
= 0x0100,
Event
= 0x0200,
Interface
= 0x0400,
Parameter
= 0x0800,
Delegate
= 0x1000,
ReturnValue = 0x2000,
All = Assembly | Module | Class | Struct | Enum |
Constructor |
Method | Property | Field | Event |
Interface | Parameter |
Delegate| ReturnValue
}
}
2.11.9 Доступ к информации, хранящейся в атрибутах
Получение информации, содержащейся в атрибутах, осуществляется с
помощью механизма, который называется отражением (Reflection).
2.11.9.1 Получение одиночного атрибута
В следующем примере атрибут DeveloperAttribute применяется к классу
MainApp в целом. Метод GetAttribute использует Attribute.GetCustomAttribute
для получения состояния атрибута DeveloperAttribute перед тем, как вывести
информацию на консоль.

using System;
[Developer("Василий Пупкин", "42", Reviewed = true)]
class MainApp
{
public static void Main()
{
// Вызвать функцию получения и отображения
атрибута.
GetAttribute(typeof(MainApp));
}
public static void GetAttribute(Type t)
{
// Получить атрибут.
DeveloperAttribute MyAttribute =
(DeveloperAttribute)Attribute.GetCustomAttribute(t,
typeof(DeveloperAttribute));
if(MyAttribute == null)
{
67
Console.WriteLine("Атрибут не найден");
}
else
{
// Получить поле Имя.
Console.WriteLine("Имя: {0}", MyAttribute.Name);
// Получить поле Уровень.
Console.WriteLine("Уровень: {0}",
MyAttribute.Level);
// Получить поле Проверено.
Console.WriteLine("Проверено: {0}",
MyAttribute.Reviewed);
}
}
}
При запуске эта программа выдает на консоль следующие строки:
Имя: Василий Пупкин
Уровень: 42
Проверено: True
Если атрибут не найден, метод GetCustomAttribute возвращает нулевое
значение. В этом примере предполагается, что атрибут определен в текущем
пространстве имен, если это не так, не забудьте импортировать
соответствующее пространство имен.
2.11.9.2 Получение списка однотипных атрибутов
В предыдущем примере ссылки на класс и атрибут передавались в метод
GetCustomAttribute. Этот код прекрасно работает, если на уровне класса
определен только один атрибут. Но если на том же уровне определено
несколько однотипных атрибутов, этот метод вернет не всю информацию. В
таких случаях нужно использовать метод Attribute.GetCustomAttributes,
который возвращает массив атрибутов. Например, если на уровне класса
определены
два
экземпляра
атрибута
DeveloperAttribute,
можно
модифицировать метод GetAttribute, чтобы получить оба.
Разумеется, для многократного задания атрибута DeveloperAttribute он
должен быть объявлен с AttributeUsage(AttributeTargets.All, AllowMultiple =
true).

public static void GetAttribute(Type t)
{
// Получить атрибут.
DeveloperAttribute [] MyAttribute =
(DeveloperAttribute
[])Attribute.GetCustomAttributes(t,
typeof(DeveloperAttribute));
68
if(MyAttribute == null)
Console.WriteLine("Атрибут не найден");
else
for (int i = 0; i < MyAttribute.Length; i++)
{
// Получить поле Имя.
Console.WriteLine("Имя: {0}",
MyAttribute[i].Name);
// Получить поле Уровень.
Console.WriteLine("Уровень: {0}",
MyAttribute[i].Level);
// Получить поле Проверено.
Console.WriteLine("Проверено: {0}",
MyAttribute[i].Reviewed);
}
}
2.11.9.3 Получение списка разнотипных атрибутов
Методы GetCustomAttribute и GetCustomAttributes не могут искать атрибут
во всем классе и возвращать все его экземпляры. Они просматривают только
один метод или поле за раз. Поэтому, если есть класс с одним атрибутом для
всех методов и нужно получить все экземпляры этого атрибута эти методы
передаются один за другим в качестве параметров GetCustomAttribute и
GetCustomAttributes.
В следующем фрагменте кода показано, как получить все экземпляры
атрибута DeveloperAttribute, определенного как на уровне класса, так и на
уровне методов.
using System;
using System.Reflection;

public static void GetAttribute(Type t)
{
// Получить атрибут уровня класса.
DeveloperAttribute att = (DeveloperAttribute)
Attribute.GetCustomAttribute(t,
typeof(DeveloperAttribute));
if(att == null)
Console.WriteLine("Класс {0} не имеет атрибута Developer\n",
t.ToString());
else
{
Console.WriteLine("Атрибут Имя на уровне класса: {0}",
att.Name);
Console.WriteLine("Атрибут Уровень на уровне класса: {0}",
att.Level);
Console.WriteLine("Атрибут Проверено на уровне класса: {0}\n",
att.Reviewed);
}
// Получить все методы данного класса и поместить их
69
// в массив объектов System.Reflection.MemberInfo.
MemberInfo [] MyMemberInfo = t.GetMethods();
// Вывести атрибуты всех методов класса
for(int i = 0; i < MyMemberInfo.Length; i++)
{
att =
(DeveloperAttribute)Attribute.GetCustomAttribute(MyMemberInfo[i],
typeof(DeveloperAttribute));
if(att == null)
Console.WriteLine("Метод {0} не имеет атрибута
Developer\n" ,
MyMemberInfo[i].ToString());
else
{
Console.WriteLine("Атрибут Имя на уровне метода {0}:
{1}",
MyMemberInfo[i].ToString(), att.Name);
Console.WriteLine("Атрибут Уровень на уровне метода {0}:
{1}",
MyMemberInfo[i].ToString(), att.Level);
Console.WriteLine("Атрибут Проверено на уровне метода
{0}: {1}\n",
MyMemberInfo[i].ToString(), att.Reviewed);
}
}
}
Для доступа к методам и полям проверяемого класса используются
методы класса System.Type. В этом примере сначала через Type запрашивается
информация об атрибутах, определенных на уровне класса, затем, через метод
Type.GetMethods получается информация обо всех атрибутах, определенных на
уровне методов. Эта информация помещается в массив объектов типа
System.Reflection.MemberInfo. Если нужны атрибуты свойств, используется
метод Type.GetProperties, а для конструкторов — Type.GetConstructors. Класс
Type имеет множество методов для доступа к элементам типа, здесь описана
только очень небольшая часть.
2.12 Исключения
Исключения в C# предоставляют структурированный, единообразный и
типобезопасный способ обработки некорректных состояний (ошибок) как на
системном уровне, так и на уровне приложений. Исключение представляет
собой экземпляр класса, производного от System.Exception, их использование
сходно с подобным механизмом в C++. При генерации исключения
выполнение текущего блока прекращается; и идет возврат управления на более
высокий уровень. На нем исключение может быть «поймано» и обработано;
70
если же этого не произошло, осуществляется переход еще выше и т. д., пока не
будет достигнут самый верхний уровень, в котором обрабатываются все
исключения.
Синтаксис в общем случае выглядит следующим образом:

try
{
блок команд, в котором может возникнуть ошибка
}
catch [(тип_исключения имя_исключения)]
{
блок обработки исключения
}
finally
{
команды, которые выполняются в любом случае — после
блоков try и catch
}
В приведенной конструкции один из блоков: catch или finally — может
отсутствовать. Если отсутствует блок catch, исключение будет обрабатываться
на более высоких уровнях (после выполнения блока finally). Возможно
использование нескольких блоков catch: для обработки различных типов
исключительных ситуаций.
Схема работы такой конструкции очень проста — если в блоке try
происходит исключение, то происходит переход на блок catch,
сгенерированное исключение передается в качестве параметра. В любом
случае (произошло исключение или нет) в конце вызывается блок команд
finally.
Если в блоке catch не указан параметр (тип исключения), в нем будет
обрабатываться любая исключительная ситуация.
2.12.1 Генерация и перехват исключения
Чтобы сгенерировать исключение необходимо создать новый объект
класса Exception или производного от него. Для передачи этого объекта
используется ключевое слово throw.

class ReverseFunction
{
public static double Calculate(double d)
{
if (d == 0)
throw new Exception("Функция не определена для
нулевого значения");
return 1/d;
71
}
public static void Main()
{
try
{
Console.WriteLine("1 / {0} = {1}", 1,
Calculate(1));
Console.WriteLine("1 / {0} = {1}", 2,
Calculate(2));
Console.WriteLine("1 / {0} = {1}", 0,
Calculate(0));
}
catch (Exception e)
{
Console.WriteLine("Ошибка! {0}", e);
}
}
}
Перехват исключения осуществляется в блоке try/catch. При
возникновении исключения выполнение кода, определенного в блоке try,
прерывается, и начинает выполняться код, определенный в ближайшем
следующем блоке catch. Если же в процессе выполнения кода в блоке try
исключений так и не возникло, блок catch полностью пропускается и
выполнение программы идет дальше согласно ее внутренней логике.
Несколько блоков catch используются в том случае, когда для разных
типов исключений необходимо выполнять различные действия. При этом
выполняется первый блок catch, соответствующий типу сгенерированного
исключения.

try
{
CalculateSpline();
}
catch (DivisionByZeroException e)
{
Console.WriteLine("Деление на ноль");
}
catch (OverflowException e)
{
Console.WriteLine("Переполнение");
}
catch (Exception e) // Обработка остальных типов
исключения
{
Console.WriteLine("Ошибка! {0}", e);
}
72
2.13 Директивы препроцессора
В C# перед компиляцией код обрабатывается специальной программой —
препроцессором. Препроцессор ищет в коде специальные директивы и в
соответствии с ними изменяет код. Часто подобные директивы выделяют
блоки кода и позволяют условно включать или исключать их из компиляции.
Для внешней параметризации препроцессора используются определения.
Для каждого определения (которое однозначно определяется своим именем)
можно сказать, что оно либо определено, либо нет; в зависимости от этого
препроцессор выполняет различные действия. Определения можно задаются с
помощью директивы #define, которая имеет следующий вид.
#define
имя_определения
После этой директивы определение с данным именем считается определенным.
Определение можно снять с помощью директивы #undef.
#undef
имя_определения
Использование директив #define и #undef возможно только в начале кода
— до любых языковых инструкций (за исключением директив препроцессора).
Область видимости определения — файл, в котором оно задано.
В отличие от C++, где директива #define использовалась для задания
макросов: фрагментов кода или значений констант, в C# она предназначена
лишь для определения символов.
C помощью определений символов можно контролировать исключение
блоков кода из компиляции. Для этого используется условная компиляция:
директивы #if, #else, #elif и #endif. Общий вид такого блока следующий.
#if
выражение1
...
#elif выражение2
...
#elif выражениеk
...
#else
...
#endif
Блоки #elif и #else могут отсутствовать. Выражение — это логическое
выражение, в котором термами являются имена определений, а их
истинностным значением — их определенность. Таким образом, если
выражение верно, то выполняется соответствующий блок.

#define DEBUG
#define VC_V7
73
using System;
public class MyClass
{
public static void Main()
{
#if (DEBUG && !VC_V7)
Console.WriteLine("Определен символ DEBUG");
#elif (!DEBUG && VC_V7)
Console.WriteLine("Определен символ VC_V7");
#elif (DEBUG && VC_V7)
Console.WriteLine("Определены символы DEBUG и
VC_V7");
#else
Console.WriteLine("Не определены ни символ
DEBUG, ни символ VC_V7");
#endif
}
}
Еще одной группой директив являются директивы, контролирующие
генерацию ошибок. Это директивы #error, #warning и #line. Их синтаксис
таков:
#error текст
#warning текст
Если компилятор встречает директиву #error или #warning, он генерирует
ошибку или предупреждение с соответствующим текстом.

#define DEBUG
public class MyClass
{
public static void Main()
{
#if DEBUG
#error DEBUG is defined
#endif
}
}
#define DEBUG
public class MyClass
{
public static void Main()
{
#if DEBUG
#warning DEBUG is defined
#endif
}
}
74
Директива #line позволяет переопределить имя файла или номер строки,
которые будут выводиться при ошибках. Значение default восстанавливает
оригинальную нумерацию. Значение hidden приводит к игнорированию строк
кода отладчиком.
#line номер_строки ["имя_файла"]
#line default
#line hidden
В приведенном примере компилятор сгенерирует два предупреждения
«Переменная объявлена, но не используется»: на строках 8 и 200.

public class MyClass
{
public static void Main()
{
#line 200
int i;
// строка 200
#line default
char c; // строка 8
}
}
Директивы #region и #endregion выделяют блок кода в регион. Регионы
удобны при работе в среде Visual Studio: редактор позволяет «сворачивать» их
в одну строчку, что облегчает чтение кода.
#region имя_региона
#endregion
Допустимо многократное вложение регионов друг в друга. Блоки
#region..#endregion и #if..#endif могут быть вложены один в другой, но не могут
перекрываться.

#region Объявление класса MyClass
public class MyClass
{
public static void Main()
{
…
}
}
#endregion
75
3. Встроенные элементы
3.1 Класс System.Math
Предоставляет константы и статические методы для тригонометрических,
логарифмических, и других общих математических функций. Все статические
члены класса являются потокобезопасными.
3.1.1
Методы
 public static decimal Abs(decimal value)
public static double Abs(double value)
public static int Abs(int value)
public static long Abs(long value)
public static float Abs(float value)
public static sbyte Abs(sbyte value)
public static short Abs(short value)
Описание:
Вычисляет абсолютное значение указанного числа. Метод
переопределен для разных типов значения (decimal, double, short, int, long, float,
sbyte).
Параметры:
value – число в диапазоне MinValue≤value≤MaxValue;
где: MaxValue
–
максимально
допустимое
значение
используемого типа;
MinValue
–
максимально
допустимое
значение
используемого типа.
Возвращает:
Возвращает абсолютное значение указанного числа – х, 0≤ х≤
MaxValue.
Замечаниe:
В случае работы метода с типами float и double, если value равно
NegativeInfinity(см. глоссарий) или PositiveInfinity, возвращаемое значение
равно PositiveInfinity, если value равно NaN – возвращаемое значение равно
NaN;
Исключение:
В случае работы метода с типами:
short — генерируется исключение OverflowException, при
условии value=MaxValue;
int,
long,
sbyte
—
генерируется
исключение
OverflowException, при условии value=MinValue.
76
 public static double Acos(double d);
Описание:
Вычисляет угол, косинус которого — указанное число.
Параметры:
d — значение косинуса; -1 ≤ d ≤ 1.
Возвращает:
Угол θ, измеряемый в радианах; 0 ≤ θ ≤ π или θ =NaN, если d <-1 или
d> 1.
 public static double Asin(double d);
Описание:
Вычисляет угол, синус которого — указанное число.
Параметры:
d — значение синуса; -1 ≤ d ≤ 1.
Возвращает:
Угол θ, измеряемый в радианах; п/2 ≤ θ ≤ п/2 или θ =NaN, если d <-1
или d> 1.
 public static double Atan(double d);
Описание:
Вычисляет угол, тангенс которого — указанное число.
Параметры:
d - значение тангенса; -1 ≤ d ≤ 1.
Возвращает:
Угол θ, измеряемый в радианах; -п/2 ≤ θ ≤ п/2 или: θ=NaN, если d =NaN;
θ=-п/2, если d=NegativeInfinity;
θ= п/2, если d=PositiveInfinity.
 public static double Atan2(double y, double x);
Описание:
Вычисляет угол, тангенс которого — частное двух заданных чисел.
Параметры:
y — координата точки по оси Oy;
x — координата точки по оси Ox;
Возвращает:
77
Угол θ, измеряемый в радианах; -п ≤ θ ≤ п, а tan(θ)=y/x, где (х,y) —
точка в декартовой системе координат. Причем θ изменяется в зависимости от
того, в каком квадранте находится точка (x, y): в 1-ом квадранте, 0 <θ <π/2;
во 2-ом квадранте, π/2 <θ ≤ π;
в 3-ем квадранте, - π <θ <-π/2;
в 4--ом квадранте, - π/2 <θ <0.
 public static double Ceiling(double a);
Описание:
Округляет заданное число а до наименьшего целого, большего или
равного а.
Параметры:
а – число.
Возвращает:
Наименьшее целое число, большее или равное a (округление в
бóльшую сторону).
 public static double Cos(double d);
Описание:
Вычисляет косинус указанного угла.
Параметры:
d – угол, измеряемый в радианах. Если угол d указан в градусах,
необходимо перевести его в радианы – d(рад)=d(град)*п/180.
Возвращает:
Косинус d.
 public static double Cosh(double value);
Описание:
Вычисляет гиперболический косинус указанного угла.
Параметры:
value – угол, измеряемый в радианах. Если угол value указан в
градусах, необходимо перевести его в радианы – value(рад)= value(град)*п/180.
Возвращает:
Гиперболический косинус value. Если value равно NegativeInfinity или
PositiveInfinity, то возвращаемое значение равно PositiveInfinity. Если value
равно NaN, то возвращаемое значение равно NaN.
 public static int DivRem (int a, int b, out int result);
78
public static long DivRem (long a, long b, out long result);
Описание:
Вычисляет частное двух чисел, передавая остаток как выходной
параметр. Метод переопределен для разных типов значения (int, long).
Параметры:
a – делимое;
b – делитель;
result – полученный остаток.
Возвращает:
Частное двух чисел – result типа int или long, в зависимости от того, с
каким типом работает данный метод.
 public static double Exp(double d);
Описание:
Вычисляет значение числа е в заданной степени.
Параметры:
d – число, определяющее степень.
Возвращает:
Число е, возведенное в степень d. Если d=NaN или d=PositiveInfinity,
возвращаемое значение совпадает с d; если d=NegativeInfinity, возвращаемое
значение равно нулю.
 public static double Floor(double d);
Описание:
Округляет заданное число d до наибольшего целого, меньшего или
равного d.
Параметры:
d – число.
Возвращает:
Наибольшее целое число, меньшее или равное a (округление в
меньшую сторону).
 public static double Log(double d);
public static double Log(double d, double NewBase);
Описание:
79
Вычисляет логарифм заданного числа. Метод, так же, переопределен
для вычисления логарифма по заданному основанию.
Параметры:
d – число, логарифм которого должен быть вычислен.
NewBase – основание логарифма.
Возвращает:
 Если метод применяется для вычисления логарифма заданного
числа:
Значение d
Возвращаемое значение
Положительное
Натуральный логарифм d; то есть ln d
Нуль
NegativeInfinity
Отрицательное
NaN
Если параметр d равен NaN, возвращается NaN. Если d равен PositiveInfinity,
возвращается PositiveInfinity.
 Если метод применяется для вычисления логарифма заданного
числа, по заданному основанию:
Значение d
Возвращаемое значение
Положительное
Если NewBase ≥ 0, возвращается
логарифм по основанию NewBase.
Иначе, NaN.
Нуль
NegativeInfinity
Отрицательное
NaN
Если параметр d равен PositiveInfinity , и NewBase не равен PositiveInfinity,
NegativeInfinity, или NaN, метод возвращает PositiveInfinity.
Если NewBase равен PositiveInfinity, и d не равен PositiveInfinity,
NegativeInfinity, или NaN, метод возвращается 0.
Если оба параметра, и d и NewBase равны PositiveInfinity, или d, или
NewBase равен NaN или NegativeInfinity, метод возвращает NaN.
Если оба параметра, и d и NewBase равны PositiveInfinity, или d, или
newBase равен NaN или NegativeInfinity, метод возвращает NaN.
 public static double Log10(double d);
80
Описание:
Вычисляет десятичный логарифм заданного числа.
Параметры:
d – число, логарифм которого должен быть вычислен.
Возвращает:
Значение d
Возвращаемое значение
Положительное
Десятичный логарифм числа d, т.е.
lg d .
Нуль
NegativeInfinity
Отрицательное
NaN
Если параметр d равен NaN, метод возвращает NaN. Если d равен
PositiveInfinity, метод возвращает PositiveInfinity.
 public static byte Max(byte val1, byte val2)
public static decimal Max(decimal val1, decimal val2)
public static double Max(double val1, double val2)
public static short Max(short val1, short val2)
public static int Max(int val1, int val2)
public static long Max(long val1, long val2)
public static sbyte Max(sbyte val1, sbyte val2)
public static float Max(float val1, float val2)
public static ushort Max(ushort val1, ushort val2)
public static uint Max(uint val1, uint val2)
public static ulong Max(ulong val1, ulong val2)
Описание:
Возвращает большее из двух заданных чисел. Метод переопределен
для разных типов значения (byte, short, int, long, float, double, Decimal, sbyte,
ushort, uint, ulong).
Параметры:
Val1 — первое число;
Val2 — второе число.
Возвращает:
Большее из двух чисел – Val1 или Val2.
 public static byte Min(byte val1, byte val2)
public static decimal Min(decimal val1, decimal val2)
81
public static double Min(double val1, double val2)
public static short Min(short val1, short val2)
public static int Min(int val1, int val2)
public static long Min(long val1, long val2)
public static sbyte Min(sbyte val1, sbyte val2)
public static float Min(float val1, float val2)
public static ushort Min(ushort val1, ushort val2)
public static uint Min(uint val1, uint val2);
public static ulong Min(ulong val1, ulong val2)
Описание:
Возвращает меньшее из двух заданных чисел. Метод переопределен
для разных типов значения (byte, short, int, long, float, double, Decimal, sbyte,
ushort, uint, ulong).
Параметры:
Val1 — первое число;
Val2 — второе число.
Возвращает:
Меньшее из двух чисел – Val1 или Val2.
 public static double Pow(double x, double y);
Описание:
Возводит заданное число в заданную степень.
Параметры:
х – основание степени — число, которое будет возведено в степень;
y – показатель степени.
Возвращает:
Число х в степени y.
Следующая таблица указывает возвращаемое значение, при различных
значениях или диапазонах значений, определенных для x и y параметров.
Параметры
x или y = NaN
Любое значение x кроме NaN; y = 0
x = NegativeInfinity; y <0
x = NegativeInfinity; y - положительное
нечетное целое число
x = NegativeInfinity; y - не 0 или
положительное нечетное целое число
x <0; (-1 <y <0) или (0 <y <1)
x <-1; y = NegativeInfinity
x <-1; y = PositiveInfinity
x =-1; y = NegativeInfinity или
82
Возвращаемое значение
NaN
1
0
NegativeInfinity
PositiveInfinity
NaN
0
PositiveInfinity
NaN
PositiveInfinity
(0> = x>-1); y = NegativeInfinity
(0> = x>-1); y = PositiveInfinity
x = 0; y <0
x = 0; y> 0
(0 <x <1); y = NegativeInfinity
(0 <x <1); y = PositiveInfinity
x - 1; y - любое значение кроме NaN
x> 1; y = NegativeInfinity
x> 1; y = PositiveInfinity
x = PositiveInfinity; y <0
x = PositiveInfinity; y> 0
PositiveInfinity
0
PositiveInfinity
0
PositiveInfinity
0
1
0
PositiveInfinity
0
PositiveInfinity
 public static decimal Round(decimal d)
public static double Round(double d)
public static decimal Round(decimal d, int value)
public static double Round(double d, int value)
Описание:
Округляет заданное число, до указанного количества знаков (или до
целого). Метод переопределен для типов decimal и double.
Параметры:
d – заданное число;
value – число значащих цифр в возвращаемом значении, т. е. заданная
точность.
Возвращает:
Если метод используется без заданной точности, то возвращается
значение d, округленное до ближайшего целого числа. Причем, если значение
d находится на половине между двумя целыми числами, то возвращается
четное число.
Если метод используется с заданной точностью, то возвращается число,
самое близкое к числу d с заданной точностью value. Причем, если значение d
находится на середине между двумя числами, то возвращается четное число.
Если точность d меньше value, то d возвращается без изменений.
Замечание:
Если метод используется для округления значения типа decimal, то value
может изменяться в пределах от 0 до 28. При value=0 возвращается целое
число.
Если метод используется для округления значения типа double, то value
может изменяться в пределах от 0 до 15.
Исключение:
ArgumentOutOfRangeException – генерируется при value<0, value>15,
если метод используется для округления значения типа double.
83
 public static int Sign(decimal value)
public static int Sign(double value)
public static int Sign(short value)
public static int Sign(int value)
public static int Sign(long value)
public static int Sign(sbyte value)
public static int Sign(float value)
Описание:
Используется для определения знака заданного числа. Метод
переопределен для разных типов значения (decimal, double, short, int, long,
sbyte, float).
Параметры:
value – число, знак которого необходимо определить.
Возвращает:
Значение
-1
0
1
Описание
value<0
value=0
value>0
Исключение:
ArithmeticException – генерируется, при value=NaN, если заданное число
value типа double или float.
 public static double Sin(double a);
Описание:
Вычисляет синус угла, заданного в радианах.
Параметры:
a – угол, заданный в радианах. Если угол a указан в градусах,
необходимо перевести его в радианы – a(рад)=a(град)*п/180.
Возвращает:
Синус угла а. При a=NaN, a=PositiveInfinity, a=NegativeInfinity –
возвращается NaN.
 public static double Sinh(double value);
Описание:
Вычисляет гиперболический синус угла, заданного в радианах.
84
Параметры:
value – угол, заданный в радианах. Если угол value указан в градусах,
необходимо перевести его в радианы – value(рад)=value(град)*п/180.
Возвращает:
Гиперболический синус угла value. При value =NaN, a=PositiveInfinity,
value=NegativeInfinity – возвращается значение, эквивалентное аргументу.
 public static double Sqrt(double d);
Описание:
Вычисляет квадратный корень указанного числа.
Параметры:
d – число.
Возвращает:
Если d>=0,возвращается положительный корень квадратный из d,
если d<0, возвращается NaN.
 public static double Tan(double a);
Описание:
Вычисляет тангенс угла, заданного в радианах.
Параметры:
a – угол, заданный в радианах. Если угол a указан в градусах,
необходимо перевести его в радианы – a(рад)=a(град)*п/180.
Возвращает:
Тангенс угла а. При a=NaN, a=PositiveInfinity, a=NegativeInfinity –
возвращается NaN.
 public static double Tanh(double value);
Описание:
Вычисляет гиперболический тангенс угла, заданного в радианах.
Параметры:
value – угол, заданный в радианах. Если угол value указан в градусах,
необходимо перевести его в радианы – value(рад)=value(град)*п/180.
Возвращает:
Гиперболический тангенс угла value. При value=PositiveInfinity,
возвращается 1, при value=NegativeInfinity, возвращается –1.Если value=NaN,
возвращается NaN.
85
3.1.2 Поля
 public const double E;
Описание:
Предоставляет основание натурального логарифма,
константой е.
Замечание:
Значение этого поля – 2.7182818284590452354.
указанное
 public const double Pi;
Описание:
Предоставляет отношение окружности круга к его диаметру,
указанное константой π.
Замечание:
Значение этого поля - 3.14159265358979323846.
86
3.2 Класс System.Random
Предоставляет генератор последовательности псевдослучайных чисел. Числа
выбираются из конечного набора с равновероятным распределением.
Все статические члены класса являются потокобезопасными; безопасность
экземплярных членов не гарантируется.
3.2.1 Методы
 public virtual bool Equals(object obj);
public virtual bool Equals(object obj1, object obj2);
Описание:
Метод унаследован от класса Object. Определяет, равны ли два
экземпляра Object. Метод переопределен и может использоваться для
сравнения как текущего объекта с заданным, так и двух заданных объектов.
Параметры:
В случае, когда сравнение производиться с текущим объектом, методу
передается один параметр:
obj – объект, который необходимо сравнить с текущим.
Если метод применяется для сравнения двух заданных объектов,
передается два параметра:
obj1, obj2 – объекты которые необходимо сравнить.
Возвращает:
True, если сравниваемые объекты равны, иначе false.
 public Type GetType();
Описание:
Метод унаследован от класса Object. Получает тип текущего
экземпляра.
Возвращает:
Тип текущего экземпляра.
 public virtual int Next();
public virtual int Next(int maxValue);
public virtual int Next(int minValue, int maxValue);
Описание:
Возвращает случайное число.
Параметры:
1.
нет
87
maxValue – верхняя граница сгенерированного случайного
числа. maxValue>=0.
3.
minValue – нижняя граница сгенерированного случайного
числа;
maxValue - верхняя граница сгенерированного случайного числа;.
maxValue>= minValue.
2.
Возвращает:
1. 32-разрядное целое неотрицательное число, меньшее чем
MaxValue, где MaxValue – наибольшее значение типа Int32.
2.
32-разрядное целое неотрицательное число, меньшее чем
maxValue, где maxValue – заданный параметр.
3. 32-разрядное целое число, большее или равное minValue, но меньшее
чем maxValue, где minValue и maxValue – заданные параметры.
Если minValue= maxValue – возвращается minValue.
Исключение:
1. нет.
2. ArgumentOutOfRangeException, если maxValue<0.
3. ArgumentOutOfRangeException, если maxValue<minValue.
 public virtual void NextBytes(byte [] buffer);
Описание:
Заполняет элементы указанного байтового массива случайными
числами.
Параметры:
buffer – байтовый массив.
Возвращает:
Байтовый массив, элементы которого заполнены случайными
числами.
Исключение:
ArgumentNullException, если buffer – нулевая ссылка.
 public virtual double NextDouble();
Описание:
Возвращает случайное число между 0.0 и 1.0.

public virtual string ToString();
88
Описание:
Метод унаследован от Object. Возвращает строковое представление
объекта.
Возвращает:
Строку, представляющую объект.
 Метод Finalize
~Object();
Описание:
Метод, унаследованный от класса Object. Позволяет объекту
освободить ресурсы и выполнить другие операции по очистке памяти перед
тем как будет вызван сборщик мусора.
 protected object MemberwiseClone();
Описание:
Метод унаследован от класса Object. Создает ограниченную копию
текущего объекта.
Возвращает:
Копию текущего объекта.
Замечание:
Метод MemberwiseClone не может быть переопределен и доступен
только через класс System.Random или производный от него.
 protected virtual double Sample();
Описание:
Возвращает случайное число между 0.0 и 1.0.
Конструктор
 Public Random();
Public Random(int seed);
Описание:
Инициализирует новый экземпляр класса Random. Метод
переопределен и может работать как с параметром, так и без параметра.
Параметры:
seed – число, задающее начальное значение псевдослучайной
последовательности чисел.
89
3.3 Структура DateTime
Описывает момент времени, выраженный через дату и время.
Далее будут выборочно рассмотрены методы, свойства и конструкторы
структуры DateTime.
3.3.1 Методы
 public string ToLongDateString();
Описание:
Используется для преобразования даты в определенный формат.
Возвращается:
Строка, содержащая день недели, название месяца, число, год.
(Например, «Tuesday, June 1, 2004» для английской версии .Net Framework)
 public string ToShortDateString ();
Описание:
Используется для преобразования даты в определенный формат.
Возвращается:
Строка, содержащая числовое представление даты. (Например:
6/1/2004)
 public string ToLongTimeString();
Описание:
Используется для преобразования время суток в определенный
формат.
Возвращается:
Строка, содержащая часы, минуты, секунды. (Например, 8:45:15 AM)
 public string ToShortTimeString ();
Описание:
Используется для преобразования время суток в определенный
формат.
Возвращает:
Строка, содержащая часы и минуты. (Например, 8:45)
 public override string ToString ();
90
public override string ToString (IFormatProvider provider);
public override string ToString (string format);
public override string ToString (string format, IFormatProvider provider);
Описание:
Позволяет форматировать дату и время в определенном формате.
Параметры:
provider – определяет интерфейс. Для этого аргумента необходим
экземпляр класса, реализуемый IFormatProvider.
format - буква или набор букв, определяющих стиль форматирования.
Возвращается:
Строка, отформатированная в соответствии с заданными
параметрами.
Исключения:
FormatException – генерируется, если format – не относится к
символам,
задающим
тип
форматирования,
определенным
в
DateTimeFormatInfo.
 public DateTime ToUniversalTime();
Описание:
Преобразовывает время к UTC (Universal
Универсальное Координированное Время).
Возвращает:
Значение DateTime, преобразованное к UTC.
Coordinated
3.3.2 Свойства
 public int Year { get;}
Описание:
Возвращает значение года в интервале от 1 до 9999.
 public int Moth { get;}
Описание:
Возвращает значение месяца в интервале от 1 до 12.
 public int Day { get;}
91
Time,
Описание:
Возвращает день — число в интервале от 1 до 31.
 public int Hour { get;}
Описание:
Возвращает значение часа в интервале от 1 до 12.
 public int Minute { get;}
Описание:
Возвращает значение минут в интервале от 0 до 59.
 public int Second { get;}
Описание:
Возвращает значение секунд в интервале от 0 до 59.
 public int Millisecond { get;}
Описание:
Возвращает значение миллисекунд в интервале от 0 до 999.
 public int DayOfWeek { get;}
Описание:
Возвращает значение дня недели от 0 (воскресенье) до 6 (суббота).
 public int DayOfYear { get;}
Описание:
Возвращает день года в интервале от 1 до 366.
 public DateTime Date { get;}
Описание:
Возвращает дату, т.е. хранящееся в объекте значение, но со временем,
установленным в 0:00:00 (полночь).
 public static DateTime Now {get;}
92
Описание:
Текущие местные дата и время.
 public static DateTime Today {get;}
Описание:
Текущая местная дата.
 public static DateTime UtcNow {get;}
Описание:
Текущие дата и время по UTC.
 public long Ticks {get;}
Описание:
Число отсчетов по 100 наносекунд, прошедших с 0:00:00 1.1.0001.
 public TimeSpan TimeOfDay {get;}
Описание:
Число отсчетов по 100 наносекунд, прошедших с полуночи.
Конструктор
 DateTime(long ticks);
DateTime(int year, int month, int day);
DateTime(int year, int month, int day, int hour, int minute, int second);
DateTime(int year, int month, int day, int hour, int minute, int second,
int msec);
DateTime(int year, int month, int day, Calendar cal);
DateTime(int year, int month, int day, int hour, int minute, int second, Calendar
cal);
DateTime(int year, int month, int day, int hour, int minute, int second, int
msec,Calendar cal);
Описание:
Инициализирует новый объект DateTime.
Параметры:
ticks – число отсчетов времени по 100 наносекунд.
year –год в диапазоне от 1 до 9999.
93
month –месяц в диапазоне от 1 до 12.
day –дни в диапазоне от 1 до числа дней в соответствующем месяце
данного года.
hour –количество часов в диапазоне от 0 до 23.
minute –количество минут в диапазоне от 0 до 59.
second –количество секунд в диапазоне от 0 до 59.
msec - количество миллисекунд в диапазоне от 0 до 999.
сal – объект типа Calendar.
Исключения:
ArgumentNullException - генерируется, если Calendar – нулевая
ссылка.
ArgumentOutOfRangeException – генерируется, если любой из
параметров выходит за разрешенные пределы.
ArgumentException – генерируется, если указанные параметры
выходят за пределы интервала (MinValue, MaxValue).
94
3.4 Структура TimeSpan
Описывает интервал времени. Далее будут выборочно рассмотрены свойства
и конструкторы структуры TimeSpan.
3.4.1 Свойства
 public int Days {get;}
Описание:
Возвращает число дней.
 public int Hours {get;}
Описание:
Возвращает число часов от 0 до 23.
 public int Minutes {get;}
Описание:
Возвращает число минут от 0 до 59.
 public int Seconds {get;}
Описание:
Возвращает количество секунд от 0 до 59.
 public int Milliseconds {get;}
Описание:
Возвращает количество миллисекунд от 0 до 999.
 public long Ticks {get;}
Описание:
Возвращает число тиков (интервалов по 100 наносекунд).
 public double TotalDays {get;}
95
Описание:
Возвращает значение временного интервала, выраженное в днях
(может включать целую и дробную части).
 public double TotalHours {get;}
Описание:
Возвращает значение временного интервала, выраженное в часах.
 public double TotalMinutes {get;}
Описание:
Возвращает значение временного интервала, выраженное в минутах.
 public double TotalSeconds {get;}
Описание:
Возвращает значение временного интервала, выраженное в секундах.
 public double TotalMilliseconds {get;}
Описание:
Возвращает
миллисекундах.
значение
временного
интервала,
выраженное
Конструктор
 TimeSpan(long ticks);
TimeSpan (int hours, int minutes, int seconds);
TimeSpan (int days, int hours, int minutes, int seconds);
TimeSpan (int days, int hours, int minutes, int seconds, int msec);
Описание:
Инициализирует новый объект TimeSpan.
Параметры:
ticks – число тиков (отсчетов времени по 100 наносекунд).
hour – количество часов.
minute – количество минут.
96
в
second – количество секунд.
msec - количество миллисекунд.
Исключения:
ArgumentOutOfRangeException – генерируется, если значение объекта
TimeSpan выходит за пределы интервала (MinValue, MaxValue).
97
4. Сообщения об ошибках компиляции
Код ошибки
CS0001
CS0003
CS0004
CS0005
CS0006
CS0007
CS0008
CS0009
CS0010
CS0011
CS0012
CS0013
CS0014
CS0015
CS0016
CS0017
CS0019
CS0020
CS0021
CS0022
CS0023
CS0025
CS0026
CS0027
CS0028
CS0029
CS0030
CS0031
Описание
Внутренняя ошибка компилятора
Недостаточно памяти
Предупреждение рассматривается как ошибка
Опции компилятора {0} требуется аргумент
Файл метаданных {0} не найден
Непредвиденная ошибка инициализации среды выполнения
.NET - {0}
Непредвиденная ошибка чтения метаданных из файла {0} {1}
Метаданные файла {0} не могут быть открыты - {1}
Невозможно объявить пространство имен и тип с
одинаковым именем {0}
Упомянутый класс {0} имеет базовый класс или интерфейс
{1}, объявленный в сборке, на которую нет ссылки.
Необходимо добавить ссылку на сборку {2}
Тип {0} объявлен в сборке, на которую нет ссылки.
Необходимо добавить ссылку на сборку {1}
Непредвиденная ошибка записи метаданных в файл {0} - {1}
Указанный файл {0} не найден
Название типа {0} слишком длинное
Невозможна запись данных в файл {0} - {1}
Программа {0} имеет больше одной точки входа:
Оператор {0} не может применяться к операндам типа {1} и
{2}
Деление на нуль
Невозможно применить индексацию при помощи [] к
выражению типа {0}
Неправильный номер индекса внутри [], ожидаемый номер {}
Оператор {0} не может применяться к операнду типа {1}
Файл стандартной библиотеки {0} не найден
Ключевое слово this нельзя использовать в статическом
свойстве, статическом методе или в инициализаторе
статического поля
Ключевое слово this неприменимо в данном контексте
{0} имеет неверную для точки входа сигнатуру
Невозможно неявное преобразование типа {0} к {1}
Невозможно преобразование типа {0} к {1}
Значение константы {0} не может быть преобразовано к типу
98
CS0032
CS0033
CS0034
CS0035
CS0036
CS0037
CS0038
CS0039
CS0040
CS0041
CS0042
CS0043
CS0050
CS0051
CS0052
CS0053
CS0054
CS0055
CS0056
CS0057
CS0058
CS0059
CS0060
{1}
Невозможно открыть файл инкрементной сборки{0} для
записи
Не хватает места на диске или ошибка I/O при записи файл
инкрементной сборки {0}
Оператор {0} является противоречивым для операндов с
типами {1} и {2}
Оператор {0} является противоречивым для операнда с
типом {1}
Параметр out не может иметь атрибут 'In'
Невозможно преобразовать null к типу {0}, потому что это
тип значения
Невозможен доступ к нестатическому члену внешнего типа
{0} через вложенный тип {1}
Невозможно преобразовать тип {0} к типу {1}
Неожиданная ошибка инициализации отладочной
информации - {0}
Неожиданная ошибка записи отладочной информации в файл
{0} - {1}
Неожиданная ошибка записи отладочной информации в файл
{0} - {1}
PDB файл имеет неправильный или устаревший формат.
Удалите его и повторите компиляцию
Несовместимый доступ: возвращаемый тип {0} менее
доступен, чем метод {1}
Несовместимый доступ: параметр типа {0} менее доступен,
чем метод {1}
Несовместимый доступ: поле типа {0} менее доступно, чем
поле {1}
Несовместимый доступ: свойство типа {0} менее доступно,
чем свойство {1}
Несовместимый доступ: индекс возвращаемого типа {0}
менее доступен, чем индекс {1}
Несовместимый доступ: параметр типа {0} менее доступен,
чем индекс {1}
Несовместимый доступ: возвращаемый тип {0} менее
доступен, чем оператор {1}
Несовместимый доступ: параметр типа {0} менее доступен,
чем оператор {1}
Несовместимый доступ: параметр типа {0} менее доступен,
чем делегат {1}
Несовместимый доступ: параметр типа {0} менее доступен,
чем делегат {1}
Несовместимый доступ: базовый класс {0} менее доступен,
99
CS0061
CS0065
CS0066
CS0067
CS0068
CS0069
CS0070
CS0071
CS0072
CS0073
CS0074
CS0075
CS0076
CS0077
CS0078
CS0079
CS0100
CS0101
CS0102
CS0103
CS0104
CS0105
CS0106
CS0107
CS0108
CS0109
CS0110
чем класс {1}
Несовместимый доступ: базовый интерфейс {0} менее
доступен, чем интерфейс {1}
{0}: событие должно содержать оба метода add и remove
{0}: событие должно быть типа delegate
Событие {0} не используется
Событие {0} не может быть инициализировано в интерфейсе
{0}: событие в интерфейсе не может содержать методы add
или remove
Событие {0} может располагаться только с левой стороны от
операторов += или -=
При выполнении события, которое было объявлено в
интерфейсе должен быть использован синтаксис свойства
{0}: невозможно переопределить; {1} не является событием
Методы add и remove в объявлении события должны иметь
тело
{0}: событие, помеченное как abstract, не может быть
инициализировано
При использовании отрицательного числа необходимо
заключить его в круглые скобки
Имя перечислителя 'value__' зарезервировано и не может
быть использовано
Оператор as должен использоваться с ссылочным типом ({0}это тип значения)
Букву {0} легко перепутать с цифрой {1}, для ясности
используйте букву {2}
Событие {0} может располагаться только с левой стороны от
операторов += или -=
Параметр с именем {0} уже объявлен
В пространстве имен {0} уже содержиться определение для
{1}
Класс {0} уже содержит определение для {1}
Имя {0} не существует в классе или пространстве имен
{0} неоднозначная ссылка
Директива using для {0} уже использовалась в этом
пространстве имен
Модификатор {0} невозможно применить для этого элемента
Указано более одного модификатора доступа
Для члена {0} требуется ключевое слово new, так как он
скрывает наследуемый член {1}
Член {0} не скрывает наследуемый член. Ключевое слово
new не требуется
В вычислении константного значения для {0} участвует
100
CS0111
CS0112
CS0113
CS0114
CS0115
CS0116
CS0117
CS0118
CS0119
CS0120
CS0121
CS0122
CS0123
CS0126
CS0127
CS0128
CS0131
CS0132
CS0133
CS0134
CS0135
CS0136
CS0138
CS0139
CS0140
CS0143
CS0144
рекурсивное выражение
В классе {0} уже определен член {1} с такими же типами
параметра
Статический член {0} не может быть помечен как override,
virtual или abstract
Член {0}, помеченный как override, не может быть помечен
как new или virtual
Функция {0} скрывает унаследованного члена {1}
{0}: нет соответствующего переопределяемого метода
Пространство имен непосредственно не содержит членов,
таких как поля или методы
{0} не содержит определения для {1}
{0} означает {1} при ожидаемом {2}
{0} означает {1}, что некорректно в данном контексте
Для нестатических полей, методов и свойств {0} требуется
ссылка на объект
Неоднозначный вызов следующих методов или свойств: {0}
и {1}
{0} недоступен из-за уровня защиты.
Метод {0} не соответствует делегату {1}
Требуется объект с типом, приводимым к типу {0}
Так как функция {0} имеет возвращаемый тип void, то после
return не должно быть выражения
Локальная переменная {0} уже определена в этой области
Левой частью выражения должна быть переменная, свойство
или индексатор
{0}: статический конструктор должен быть без параметров
Переменная {0}, объявленная как const, должна иметь
постоянное значение
При объявлении вложенного пространства имен нельзя
использовать составное имя
{0} противоречит объявлению {1}
Локальная переменная с именем {0} не может быть
объявлена в этой области видимости, так как это даст другой
смысл переменной {0}, которая уже объявлена в {1} области
видимости
Ключевое слово using применяется для объявления
пространства имен; {0}-это класс, а не пространсво имен
Нет соответствующего цикла, из которого надо выйти по
break или continue
Метка {0} уже существует
Тип {0} не имеет конструктора
Невозможно создать экземпляр абстрактного класса или
101
CS0145
CS0146
CS0148
CS0149
CS0150
CS0151
CS0152
CS0153
CS0154
CS0155
CS0156
CS0157
CS0158
CS0159
CS0160
CS0161
CS0162
CS0163
CS0164
CS0165
CS0167
CS0168
CS0169
CS0170
CS0171
CS0172
CS0173
CS0174
CS0175
CS0176
CS0177
интерфейса {0}
Значение постоянного поля должно быть задано {0}
Рекурсивное определение базового класса между {0} и {1}
У делегата {0} нет конструктора
Ожидается название метода
Ожидается значение константы
Ожидается значение перечисляемого типа
Метка {0} уже используется в этом выражении
Goto case имеет силу только внутри выражения switch
Свойство или индексатор {0} не может использоваться в
данном контексте из-за ограничения доступа
Тип выбрасываемого или перехватываемого объекта должен
быть производным от System.Exception
Выражение throw без аргументов недопустимо вне блока
catch
Нельзя передать управление из блока finally
Одна и та же метка {0} используется как во внутренней
области, так и во внешней
Метка {0} не существует в пределах области выражения goto
Предыдущий блок catch уже перехватывает все исключения
этого или вышестоящего типа
{0}: не все ветви кода возвращают значение
Обнаружен недоступный код
Управление не может быть передано из одной метки case
({0}) в другую
Эта метка не используется
Использование неинициализированной локальной
переменной {0}
У делегата {0} нет метода Invoke
Переменная {0} объявлена, но нигде не используется
Поле {0} нигде не используется
Использование неинициализированного поля {0}
Поле {0} должно быть инициализировано в конструкторе
Тип условного выражения невозможно определить, так как
{0} и {1} неявно преобразовываются друг к другу
Тип условного выражения невозможно определить, так как
не существует преобразования между {0} и {1}
Для ссылки необходим базовый класс
использование ключевого слова в данном контексте
бессмысленно
К статическому члену {0} нельзя обращаться через
экземпляр; используйте квалификатор типа.
Значение параметра {0} должно быть определено в текущем
102
CS0178
CS0179
CS0180
CS0182
CS0183
CS0184
CS0185
CS0186
CS0187
CS0188
CS0191
CS0192
CS0193
CS0196
CS0197
CS0198
CS0200
CS0201
CS0202
CS0204
CS0205
CS0206
CS0208
CS0209
CS0210
методе
Неправильная структура инициализации массива
{0}, помеченный как extern, не может быть объявлен внутри
класса
{0} не может быть одновременно extern и abstract
Аргументом атрибута должно быть константное выражение,
выражение typeof или выражение создания массива
Данное выражение всегда имеет предусмотренный ({0}) тип
Данное выражение имеет непредусмотренный ({0}) тип
{0}-не является ссылочным типом, как требует опереатор
lock
Использование null невозможно в этом контексте
Нет такого оператора {0}, определенного для типа {1}
Этот объект не может использоваться пока все поля не
инициализированы
Присвоить значение полю readonly можно только в
конструкторе или при объявлении
Поле, отмеченное как readonly, нельзя передавать в качестве
out или ref параметра (только в конструкторе)
Оператор * или оператор -> должен применяться к
указателям
Указатель должен быть индексирован только однм значением
Присвоить значение статическому полю readonly можно
только в статическом конструкторе или при инициализации
Статическое поле readonly не может быть предано ка ref или
out параметр (только в статическом конструкторе)
Нельзя присвоить значение свойству или индексатору {0}возможно только чтение
Только операции присваивания, вызова, инкремента,
декремента, или объявление нового объекта могут
использоваться в качестве предложения
Запрос GetEnumerator должен возвращать класс или
структуру, а не {0}
Предельно допустимое число локальных переменных - 65535
Невозможно вызвать абстрактный метод
Свойство или индексатор невозможно использовать в
качестве ref или out параметров
Невозможно получить адрес или размер переменной
управляемого типа ({0})
Локальные переменные, объявленные в выражении fixed
должны быть типа указателя
Вы должны обеспечить инициализацию в выражении fixed
или using
103
CS0211
CS0212
CS0213
CS0214
CS0215
CS0216
CS0217
CS0218
CS0219
CS0220
CS0221
CS0225
CS0227
CS0228
CS0229
CS0230
CS0231
CS0233
CS0234
CS0236
CS0238
CS0239
невозможно получить адрес данного выражения
Адрес unfixed выражения можно получить только внутри
инициализации выражения fixed
Ненужно использовать выражение fixed для получения уже
фиксированного адреса
Указатели могут использоваться только в контексте unsafe
Возвращаемые операторы true и false должны бать типа boоl
Чтобы определить оператор {0} необходимо определить
соответствущий оператор {1}
Для того, чтобы быть применимым в качестве 'коротковычисляемого' оператора, определяемый пользователем
оператор {0} должен возвращать результат тогоже типа, что
и 2 принимаемых параметра
Тип должен содержать объявление оператора true и
оператора false
переменная {0} объявлена, но ее значение нигде не
используется
Выход за пределы допустимости во время компиляции блока
checked
Значение константы не может быть конвертировано к {0}
(для переопределения используйте синтаксис {1})
При использовании параметра params необходимо задавать
одномерный массив
Если в коде содержиться ключевое слово unsafe, то при
компиляции должна использоваться опция компилятора
/unsafe
Тип не содержит определения для {0}, или нет доступа к {0}
Неопределенность между {0} и {1}
При использовании выражения foreach необходимо
передавать как тип, так и идентификатор
Параметр params должен быть последним параметром в
списке передаваемых параметров
Оператор sizeof может использоваться только в блоке unsafe
(предполагается использование
System.Runtime.InteropServices.Marshal.SizeOf)
Тип или пространство имен {0} не существует в классе или
пространстве имен {1} (возможно, вы пропустили ссылку на
сборку)
При инициализации поля нельзя использовать нестатическое
поле, метод или свойство {0}
Модификатор sealed нельзя применять к {0}, так как он не
помечен как override
{0}:нельзя наследовать член {1}, так как он помечен как
sealed
104
CS0241
CS0242
CS0243
CS0244
CS0245
CS0246
CS0247
CS0248
CS0249
CS0250
CS0251
CS0252
CS0253
CS0254
CS0255
CS0500
CS0501
CS0502
CS0503
CS0504
CS0505
CS0506
CS0507
Параметрические методы не могут иметь значения по
умолчанию
Операция не определена для пустого указателя
Атрибут Conditional непременим к методу {0}, так как этот
метод отмечен как override
Ключевые слова is и as нельзя использовать для типов
указателя
Деструкторы и object.Finalize не могут быть вызваны
напрямую. Вызывайте IDisposable.Dispose, если он
существует
Тип или пространство имен с именем {0} не найдено
(возможно, вы пропустили директиву using или указатель на
сборку)
В выражении stackalloc нельзя использовать отрицательное
число
Размер массива не может быть отрицательным
Вместо переопределения object.Finalize. используйте
синтаксис деструктора
Не надо вызывать базовый класс метода Finalize. Это
делается автоматически из деструктора
В массиве нельзя использовать отрицательный индекс
(индексы в массиве всегда начинаются с 0)
Сравнение ссылки; чтобы сравнить значения, необходимо
осуществить операцию приведения типов
Возможно непреднамеренное сравнение ссылок; для
сравнения значений нужно привести правую часть
выражения к типу {0}
В выражении fixed, справо от знака равенства, нельзя
выполнять операцию приведения типов
Ключевое слово stackalloc нельзя использовать в блоках catch
или finally
{0} не может объявляться с телом, так как он отмечен как
abstract
{0} должен объявляться с телом, так как о не отмечен как
abstract или extern
Класс {0} не может быть помечен сразу двумя
модификаторами: abstract и sealed
Абстрактный метод {0} не может быть помечен как virtual
Константа {0} не может быть статической
{0}: не может быть переопределена; {1}: не является
функцией
{0}: не может быть переопределен унаследованный член {1},
так как он не отмечен как virtual, abstract, или override
{0}: невозможно изменить модификатор доступа при
105
CS0508
CS0509
CS0513
CS0514
CS0515
CS0516
CS0517
CS0518
CS0519
CS0520
CS0522
CS0523
CS0524
CS0525
CS0526
CS0527
CS0528
CS0529
CS0531
CS0533
CS0534
CS0535
CS0536
CS0537
CS0538
CS0539
CS0540
CS0541
переопределении {1} наследуемого метода {2}
{0}: невозможно изменить тип возвращаемого значения у
замещенного метода {0}
{0}: невозможно наследование изолированного класса {1}
Неабстрактный класс {1} не может содержать абстрактную
функцию {0}
{0}: статический конструктор не может явно вызывать
конструктор базового класса
{0}: модификаторы доступа нельзя использовать в
статическом конструкторе
Конструктор {0} не может вызывать сам себя
{0}: не имеет базового класса и не может вызывать базовый
конструктор
предписанный тип {0} не определен или не импортирован
{0} конфликтует с предписанным пространством имен
{0} конфликтует с предписанным типом
{0}: структура не может вызывать конструктор базового
класса
Член структуры {0} типа {1} вызывает зацикливание внутри
структуры
{0}: в интерфейсе нельзя определять типы
Интерфейсы не могут содержать поля
Интерфейсы не могут содержать конструкторы
{0}: список интерфейсов не может содержать тип
{0}: интерфейс уже содержится в списке интерфейсов
Наследуемый интерфейс {0} создает циклическую иерархию
с {1}
{0}: члены интерфейса не могут иметь определение. Методы,
объявленные в интерфейсе, реализуются в классе, который
унаследует этот интерфейс
{0}: скрывает унаследованный абстрактный член {1}
{0}: не реализован унаследованный абстрактный члены {1}
В классе {0} не реализован унаследованный член {1}
В классе {0} не реализован член интерфейса {1}. {2}
является статическим, не public или имеет неверный
возвращаемый тип
Класс System.Object не может иметь базовый класс или
реализовывать интерфейс
{0} в явном объявлении интерфейса - не интерфейс
{0} в явном объявлении интерфейса - не член интерфейса
{0}: класс не может реализовать интерфейс {1}, так как
интерфейс не наследуется данным классом
{0}: явное объявление интерфейса возможно только в классе
106
CS0542
CS0543
CS0544
CS0545
CS0546
CS0547
CS0548
CS0549
CS0550
CS0551
CS0552
CS0553
CS0554
CS0555
CS0556
CS0557
CS0558
CS0559
CS0560
CS0561
CS0562
CS0563
CS0564
CS0567
или в структуре
{0}: имена членов типа не должны совпадать с именами
самих типов
{0}: значение перечислителя находится вне диапазоне
данных типа
{0}: невозможно переопределить; {1} - не свойство
{0}: невозможно переопределить, так как {1} не имеет
аксессора get
{0}: невозможно переопределить, так как {1} не имеет
аксессора set
{0}: свойство ли индексатор не могут иметь тип void
{0}: свойство или индексатор должны иметь хотя бы один
аксессор
{0} - новый виртуальный член в изолированном классе {1}
Добавленный аксессор {0} не найден в члене интерфейса {1}
Явная реализация интерфейса {0} пропускает аксессор {1}
{0}: пользователь определил преобразование в/из интерфейса
{0}: определенное пользователем преобразование в/из
базового класса
{0}: определенное пользователем преобразование в/из
производного класса
Определенный пользователем оператор не может
использовать объект незакрытого типа и конвертировать его
в незакрытый тип
Определенное пользователем преобразование должно
конвертировать в/из незакрытого типа
Повторяется преобразование в классе {0}
Определенный пользователем оператор {0} должен быть
объявлен как static и public
Параметр и возвращаемый тип операторов ++ и -- должны
быть типа, содержащего эти параметры
Аксессор {0}: невозможно переопределить {1}, так как {2}скрытый метод
{0}: невозможно переопределить {1}, так как это
специальный метод компилятора
Параметр унарного оператора должен быть типа,
содержащего этот оператор
Один из параметров бинарного оператора должен быть типа,
содержащего этот оператор
Первый операнд перегруженного оператора сдвига должен
быть типа, содержащего этот оператор, второй операнд
должен иметь тип int
Интерфейсы не могут содержать операторы
107
CS0568
CS0569
CS0570
CS0571
CS0572
CS0573
CS0574
CS0575
CS0576
CS0577
CS0578
CS0579
CS0580
CS0581
CS0582
CS0583
CS0584
CS0585
CS0586
CS0587
CS0588
CS0589
CS0590
CS0591
CS0592
CS0594
CS0596
CS0597
CS0599
CS0601
CS0602
Структура не может содержать конструктор без параметров
{0}: невозможно переопределить {1},так как данная
операция не поддерживается языком
{0} ссылается на тип, который не поддерживается языком
{0}: невозможен явный вызов оператора или аксессора
{0}: Нельзя ссылаться на тип через выражение; используйте
{1}
{0}: в структуре нельзя инициализировать поля
Имя деструктора должно совпадать с именем класса
Только классы могут содержать деструкторы
Пространство имен {0} уже содержит определение для {1}
Атрибут Conditional нельзя применять к {0}, потому что это
конструктор, деструктор, оператор или явная реализация
интерфейса
Атрибут Conditional нельзя применять к {0}; это возможно
только в том случае, если функция возвращает тип void
Повтор атрибута {0}
Неправильно заданы аргументы атрибута {0}
Указанные аргументы невозможно использовать в атрибуте
{0}
Атрибут Conditional нельзя применять к членам интерфейса
Внутренняя ошибка компилятора. Вероятный виновник - {1}.
Пожалуйста, создайте файл сообщения об ошибке с опцией
компилятора {1} и предоставьте отчет о вашей проблеме
Внутренняя ошибка компилятора: стадия {0}, символ {1}
Внутренняя ошибка компилятора: стадия {0}
Внутренняя ошибка компилятора: стадия {0}
Внутренняя ошибка компилятора: стадия {0}
Внутренняя ошибка компилятора: стадия 'LEX'
Внутренняя ошибка компилятора: стадия 'PARSE'
Определенные пользователем операторы не могут
возвращать тип void
Недействительное значение аргумента атрибута {0}
Атрибут {0} нельзя использовать в объявлении этого типа.
Это возможно только в объявлениях {1}
Указанная константа вне диапазона типа {0}
Атрибут ComImport должен быть указан с атрибутом Guid
Атрибут {0} не имеет необходимого числа аргументов
{0} - невозможное значение для аргумента атрибута
Метод, к которому применяется атрибут DllImport должен
быть отмечен как 'static' и 'extern'
{0}: эту особенность языка лучше не ипользовать.
Используйте {1}
108
CS0609
CS0610
CS0611
CS0612
CS0616
CS0617
CS0618
CS0619
CS0620
CS0621
CS0622
CS0623
CS0625
CS0626
CS0628
CS0629
CS0631
CS0633
CS0634
CS0635
CS0636
CS0637
CS0641
Невозможно применить атрибут к индексатору, помеченному
как override
Поле или свойство не может быть типа {0}
Массив элементов не может быть типа {0}
{0}: не является классом атрибута
{0}: не является классом атрибута
{0} не является корректно названным аргументом атрибута.
Аргументом атрибута должны быть поля, которые не
определены как readonly, static или const, или нестатические
свойства для чтения/записи
Член класса {0} устаревший: {1}
Член класса {0} устаревший: {1}
Индексатор не может быть типа void
{0}: виртуальные или абстрактные члены не могут быть
закрытыми (private)
Выражение инициализации массива можно использовать
только при объявлении массивных типов
Инициализаторы массивов могут использоваться только при
инициализации переменных и полей
{0}: когда к структуре явно применяется атрибут
StructLayout, ко всем полям этой структуры должен быть
применен атрибут FieldOffset
Метод, оператор или аксессор {0} отмечен как внешний
(external) не имеет атрибутов. Добавьте атрибут DllImport,
что бы обеспечить внешнее выполнение
{0}: изолированный класс (sealed) не может содержать в себе
защищенных членов (protected), так как использование
защищенного члена другим классом при наследовании
исключено
Условный член {0} не может реализовать член интерфейса
{1}
Индексаторы не могут иметь out или ref параметры
Аргументом атрибута IndexerName должен быть индексатор
{0}: аргумент верен только для маршаллера типа
System.Interop.UnmanagedType.CustomMarshaller
{0}: System.Interop.UnmanagedType.CustomMarshaller требует
определенное название аргументов ComType и Marshal
Атрибут FieldOffset может применяться только к членам,
находящимся внутри типов, к которым применяется
StructLayout(LayoutKind.Explicit)
Атрибут FieldOffset нельзя применять к статическим и
постоянным полям
{0}: атрибут может применяться только к классам,
полученным из System.Attribute
109
CS0642
CS0643
CS0644
CS0645
CS0646
CS0647
CS0648
CS0649
CS0650
CS0652
CS0653
CS0654
CS0655
CS0656
CS0657
CS0658
CS0659
CS0660
CS0661
CS0662
CS0663
CS0664
CS0665
CS0666
CS0667
Возможно ошибочное пустое выражение
{0}: аргумент с таким именем уже использовался
{0} не может унаследовать особый класс {1}
Идентификатор слишком длинный
Нельзя применять атрибут DefaultMember к типу,
содержащему индексатор
Ошибка имитации атрибута {0} - {1}
{0}: этот тип не поддерживается языком
Значение поля {0} нигде не задано и будет всегда иметь
значение по умолчанию {1}
Синтаксическая ошибка, неправильное объявление массива.
При объявлении спецификатор массива предшествует
идентификатору переменной
Сравнение с целочисленной константой бесполезно.
Константа находится вне диапазона типа {0}
Невозможно применить класс атрибута {0}, так как он
является абстрактным
Невозможен вызов метода {0} без круглых скобок
Неправильное расположение атрибута {0}. Все атрибуты в
этом блоке будут проигнорированы
Отсутствует требуемый компилятором член {0}
Неверное местоположение атрибута {0}. Правильное
местоположение - {1}
Неверное местоположение атрибута {0}. Все атрибуты в этом
блоке будут игнорироваться
{0} переопределяет Object.Equals(object o), но не
переопределяет Object.GetHashCode()
{0} определяет оператор == и !=, но не переопределяет
Object.Equals(object o)
{0} определяет оператор == и !=, но не переопределяет
Object.GetHashCode()
{0}: нельзя определить только out атрибут у параметра ref.
Используйте или оба атрибута сразу (In и Out), или ни одного
{0}: методы не могут отличаться только использованием out
или ref параметра
Константа типа double не может быть преобразована к типу
{0}. Используйте суффикс для создания константы данного
типа
Нельзя использовать оператор = в условном выражении.
Попробуйте использовать оператор ==
{0}: в структуре объявлен защищенный (protected) член
Опциональный атрибут методов 'MarshalAs' теперь запрещен.
Вместо этого используйте атрибут 'return: переопределение
местоположения' с атрибутом 'MarshalAs'
110
CS0668
CS0669
CS0670
CS0672
CS0673
CS0674
CS0675
CS0676
CS0677
CS0678
CS0682
CS0683
CS0684
CS0688
CS0690
CS1001
CS1002
CS1003
CS1004
CS1005
CS1007
CS1008
CS1009
CS1010
CS1011
Два индексатора имеют одинаковые имена; атрибут
IndexerName должен использоваться с одним и тем же
именем в пределах одного типа
Класс с атрибутом ComImport не может иметь определенный
пользователем конструктор
Поле не может быть типа void
Член {0} - переопределенный устаревший член {1}.
Примените атрибут Obsolete к {0}
System.Void не может быть использован в С#. Чтобы
получить объект типа void используйте typeof(void)
Вместо {0} используйте ключевое слово {1}
Использование побитового or для расширенного знакового
операнда; рассмотрите возможность первоначального
приведения к меньшему беззнаковому типу
Нельзя передавать переменную, помеченную ключевым
словом volatile {0} в качестве out или ref параметра
Переменная, объявленная с помощью ключевого слова
volatile {0} не может быть типа {1}
Поле {0} не может быть объявлено одновременно как volatile
и readonly
{0} не может реализовать {1}, потому что это не
поддерживается языком
Явно реализованный метод {0} не может реализовать {1},
потому что это аксессор
Если к интерфейсу {0} применяется {1}, то необходимо
применить и {2}
{0}(метод, аксессор свойства или аксессор события) имеет
требование соединения, но при этом переопределяет или
реализует {1}(метод, аксессор свойства или аксессор
события), который не имеет требования соединения.
Возможно возникновение проблемы безопасности
Входной файл {0} не является корректным PE-файлом,
потому что содержит искаженные метаданные
Ожидается идентификатор
Ожидается ;
Синтаксическая ошибка, ожидается {0}
Повтор модификатора {0}
Косвенное управление типом невозможно
Свойство аксессора уже определено
Ожидается тип byte, sbyte, short, ushort, int, uint, long, или
ulong
Неизвестная последовательность символов
Разделитель в константе
Пустая символьная константа
111
CS1012
CS1013
CS1014
CS1015
CS1016
CS1017
CS1018
CS1019
CS1020
CS1021
CS1022
CS1023
CS1024
CS1025
CS1026
CS1027
CS1028
CS1029
CS1030
CS1031
CS1032
CS1033
CS1034
CS1035
CS1036
CS1037
CS1038
CS1039
CS1040
CS1041
CS1043
CS1044
CS1055
CS1501
CS1502
Слишком много символов в символьной константе
Невозможное число
Ожидается get или set аксессор
Отсутствует объект, строка или тип класса
Ожидается название аргумента атрибута
Выражение try уже имеет блок catch
Ожидается ключевое слово this или base
Ожидается перегружаемый унарный оператор
Ожидается перегружаемый бинарный оператор
Слишком большая целая константа
Ожидается определение типа или пространства имен, или
'конец файла'
Внедренное выражение не может быть декларацией или
оператором с меткой
Ожидается директива препроцессора
Ожидается однострочный комментарий или признак конца
строки
Ожидается )
Ожидается директива #endif
Неожиданная директива препроцессора
#error: {0}
#warning: {0}
Ожидается тип
Директивы препроцессора #define/#undefine должны
использоваться в начале программы
Превышен предел компилятора: файл не может содержать
более {0} линий
Превышен предел компилятора: строка не может содержать
более {0} знаков
Найден конец файла, ожидается {0}
Ожидается ( или .
Ожидается перегруженный оператор
Ожидается директива #endregion
Незаконченная строка
Директивы препрцессора должны находиться в начале строки
Ожидается идентификатор, а не ключевое слово {0}
Ожидается { или ;
Нельзя использовать больше одного типа в выражениях for,
using, fixed или при объявлении
Ожидается аксессор add или remove
Нет перегруженного метода {0}, имеющего {1} параметров
Перегруженный метод соответствует {0}, но имеет
некорректные аргументы
112
CS1503
CS1504
CS1507
CS1508
CS1509
CS1510
CS1511
CS1512
CS1513
CS1514
CS1515
CS1517
CS1518
CS1519
CS1520
CS1521
CS1522
CS1523
CS1524
CS1525
CS1526
CS1527
CS1528
CS1529
CS1530
CS1533
CS1534
CS1535
Аргумент {0}: невозможно преобразовать тип {1} к типу {2}
Невозможно открыть исходный файл {0} ({1})
Невозможно ссылаться на ресурсный файл, когда идет
построение модуля
Идентификатор ресурса {0} уже использовался в этой сборке
Упомянутый файл {0} не является сборкой.
В качестве out или ref параметра должна использоваться
переменная, а не число
Ключевое слово base бесполезно использовать в статическом
методе
Ключевое слово base бесполезно использовать в данном
контексте
Ожидается }
Ожидается {
Ожидается {0}
Недействительное выражение препроцессора
Внутри пространства имен можно объявлять классы,
делегаты, перечисления, интерфейсы, структуры и
пространства имен
Недействительный символ {0} в объявлении класса,
структуры или члена интерфейса
Класс, структура или метод интерфейса должен иметь
возвращаемый тип
Недопустимый базовый тип
Пустой блок switch
В блоке switch коду должно предшествовать ключевое слово
case или default
Ожидается блок catch или finally
Недействительный термин {0} в выражении
Оператор new требует после типа () или []
Элементы пространства имен не могут быть объявлены как
private, protected, или protected internal
Ожидается ; или = (нельзя задавать аргументы конструктора
в объявлении)
Предложение using должно предшествовать всем другим
элементам пространства имен
Ключевое слово new нельзя применять к элементам
пространства имен
Метод Invoke для делегата не может быть вызван
непосредственно
Метод перегруженного бинарного оператора {0} может
принимать только два параметра
Метод перегруженного унарного оператора {0} может
113
CS1536
CS1537
CS1540
CS1541
CS1542
CS1545
CS1546
CS1547
CS1548
CS1549
CS1551
CS1552
CS1553
CS1554
CS1555
CS1556
CS1557
CS1558
CS1559
CS1560
CS1562
CS1563
CS1565
CS1566
CS1567
CS1569
CS1570
принимать только один параметр
Недействительный параметр типа void
Using {0} уже объявлено в этом пространстве имен
Невозможен доступ к защищенному члену {0} посредством
спецификатора типа {1}; спецификатор должен быть типа
{2}
Некорректное подключение опции: {0} - не может
подключить директории
{0} является сборкой и не может быть добавлена в сборку;
используйте опцию '\R'
Свойство, индексатор или событие {0} не поддерживается
языком; попытайтесь вызвать непосредственно методы 'set
accessor' или 'get accessor'
Свойство, индексатор или событие {0} не поддерживается
языком; попытайтесь вызвать непосредственно метод {1}
Ключевое слово {0} не может быть использовано в данном
контексте
Криптографическая ошибка при подписывании сборки {0} {1}
Не найдена соответствующая криптографическая служба
Индексатор должен иметь, по крайней мере, один параметр
Спецификатор типа аrray, [], должен находиться перед
именем параметра
Объявление недействительно; используйте {0}
Объявление недействительно; используйте {0}
Не найден {0} для метода Main в программе {1}
{0}, указанный для метода Main должен являться
действительным классом или структурой
{0}, указанный в методе Main, не найденный в программе
{0}, был найден в {1}
{0} не имеет соответствующего метода Main
{0} импортирован и не может использоваться как точка
входа в прогрмму {1}
Имя файла, указанное с директивой #line, слишком длинное
Для выходных данных без исходного кода должна быть
указана опция \out
Выходной файл {0} не имеет исходного кода
Конфликтуют выбранные опции компилятора: /win32res и
/win32ico
Ошибка чтения файла ресурса {0} - {1}
Ошибка генерации ресурса Win32: {0}
Ошибка генерации файла XML документации {0} ({1})
XML комментарии в {0} имеет неправильный XML формат 114
CS1571
CS1572
CS1573
CS1574
CS1575
CS1576
CS1577
CS1578
CS1579
CS1580
CS1581
CS1583
CS1584
CS1585
CS1586
CS1587
CS1588
CS1589
CS1590
CS1591
CS1592
CS1593
CS1594
CS1595
{1}
XML комментарии имеет дубликат тэга param для {0}
XML комментарии имеет тэг param для {0}, но параметра с
таким именем нет
Параметр {0} не имеет соответствующего тэга param в XML
комментарии (другие параметры имеют)
XML комментарий имеет атрибут cref {0},но такой атрибут
не найден
В выражении stackalloc должны использоваться квадратные
скобки ([])
Номер линии, указанный в директиве #line, отсутствует или
недействителен
Ошибочная генерация сборки - {0}
Ожидается имя файла, однострочный комментарий или конец
строки
Выражение foreach не может работать с переменными типа
{0}, так как {1} не содержит определение для {2}
В атрибуте cref XML комментария неправильно указан тип
для параметра {0}
В атрибуте cref XML комментария указан неправильный
возвращаемый тип
Файл {0} не является корректным ресурсным файлом Win32
XML комментарий на {0} имеет синтаксически
некорректный атрибут cref {1}
Модификатор члена {0} должен указываться перед типом
члена и его именем
При создании массива необходимо его инициализировать или
указать размер массива
XML комментарий указан для элемента языка, который не
подлежит XML комментированию
Невозможно определить директорию общеязыковой среды
выполнения (CLR) - {0}
Невозможно включить XML фрагмент {0} в файл {1} - {2}
Некорректный XML элемент include - пропущен атрибут file
Отсутствует XML комментарий к типу или члену {0}
Некорректно составленный XML в комментариях,
подключающих файл - {0}
Указанное число аргументов ({1}) при обращении к делегату
{0} не совпадает с числом аргументов, объявленным при
декларации делегата
Некоторые аргументы делегаты {0} - недействительны
{0} определен в нескольких местах; используйте
определение из {1}
115
CS1596
CS1597
CS1598
CS1599
CS1600
CS1601
CS1602
CS1603
CS1604
CS1605
CS1606
CS1607
CS1608
CS1609
CS1610
CS1611
CS1612
CS1613
CS1614
CS1618
CS1619
CS1900
CS1901
CS1902
CS1904
XML документация не обновилась в процессе пошагового
построения; используйте ключ /incremental, чтобы обновить
XML документацию
Точка с запятой после метода или блока аксессора
недействительна
XML анализатор не может быть загружен по следующей
причине: {0}. Файл XML документации {1} не будет
сгенерирован
Метод или делегат не может возвращать тип {0}
Компиляция отменена пользователем
Параметр метода или делегата не может быть типа {0}
{0} уже определен в этой сборке
Пошаговое построение требует целевое имя, указанное с
помощью \out
Невозможно переопределить {0}, так как переменная
определена только для чтения
Невозможно передать {0} как out или ref параметр, так как
переменная определена только для чтения
Подписывание сборки не удалось; выход может быть не
подписан - {0}
Генерация сборки - {0}
Атрибут RequiredAttribute нельзя применять к типам,
определенным в С#
Нельзя указывать модификаторы при объявлении аксессоров
Невозможно удалить временный файл {0}, служащий
ресурсом Win32 по умолчанию - {1}
Параметр params не может быть объявлен как ref или out
Невозможно изменить возвращаемое значение {0}, потому
что оно не является переменным
Управляемый класс-обертка {0} кокласса для интерфейса {1}
неверен или не может быть найден (возможно, не указана
ссылка на сборку)
Неоднозначно задан атрибут {0}; используйте '1' или '2'
Невозможно создать делегат с {0}
Невозможно создать временный файл {0} - {1}
Значение уровня предупреждений должно быть в диапазоне
от 0 до 4
Указаны конфликтующие опции компилятора:
предупреждение нулевого уровня. Рассматривайте
предупреждение как ошибку
Неправильная опция {0} для /debug; должно быть либо full,
либо pdbonly
{0} - невозможный номер предупреждения
116
CS2000
CS2001
CS2002
CS2003
CS2005
CS2006
CS2007
CS2008
CS2011
CS2012
CS2013
CS2014
CS2015
CS2016
CS2017
CS2018
CS2019
CS2020
CS2021
CS2022
CS2023
CS2024
CS3001
CS3002
CS3003
CS3004
CS3005
CS3006
CS3008
CS3009
CS3010
Неожиданная ошибка инициализации компилятора
Исходный файл {0} не найден
Исходный файл {0} определен многократно
Файл ответа {0} включен многократно
Отсутствует спецификация для опции командной строки {0}
Синтаксическая ошибка командной строки: отсутствует {0}
для включения {1}
Неизвестная опция командной строки: {0}
Не указаны входы
Невозможно открыть файл ответа {0}
Не открывается файл для записи {0}
Неверное значение {0} для базы образа
Опция компилятора {0} устарела, вместо нее используйте
{0}
{0} - бинарный файл. Компилятор ожидает файл исходного
кода
Кодовая страница некорректна или не инсталлирована
Невозможно определить \main при создании модуля или
библиотеки
Невозможно найти файл сообщений 'cscmsgs.dll'
Неправильный целевой тип для \target: должно быть 'exe',
'winexe', 'library', или 'module'
Только первый набор файлов может компилироваться в
целевой модуль, отличный от {0}
Имя файла {0} слишком длинное или недопустимое
Опции '/out' и '/target' должны располагаться перед именами
исходных файлов
Опция /noconfig игнорируется, так как она была определена в
файле ответа
{0} - недопустимый номер выравнивания раздела файла
Аргумент типа {0} CLS-несовместим
Возвращаемый тип метода {0} CLS-несовместим
Тип переменной {0} CLS-несовместим
Разбиение и смешивание символов уникода CLSнесовместимо
Идентификатор {0} отличается от уже объявленного
идентификатора только регистром. Это CLS-несовместимо
Перегружаемый метод {0} отличается только
спецификаторами out или ref . Это CLS-несовместимо
Идентификатор {0} CLS-несовместим
{0}: базовый тип {1} CLS-несовместим
{0}: CLS-совместимые интерфейсы должны содержать CLSсовместимые методы
117
CS3011
CS3012
CS3013
CS3014
CS3015
CS3016
CS5000
CS5001
{0}: только CLS-совместимые члены могут быть
абстрактными
В сборке необходимо задавать CLS-совместимые атрибуты
Добавленный модуль CLS-несовместим, или пропущен
атрибут CLSCompliant
{0} не может быть помечен как CLSCompliant, так как сборка
не помечена как CLSCompliant
{0} не имеет доступных конструкторов, которые используют
только CLS-совместимые типы
Массивы или аргументы атрибутов CLS-несовместимы
{0} - неизвестная опция компилятора
Программа {0} не имеет определенной точки входа
(отсутствует метод main)
118
Глоссарий
PositiveInfinity – константа. Значение этой константы — результат деления
положительного числа нулем. Эта константа возвращается, когда результат
операции больше чем MaxValue.
NegativeInfinity – константа. Значение этой константы — результат деления
отрицательного числа нулем. Эта константа возвращается, когда результат
операции — меньше чем MinValue.
NaN-константа. Значение этой константы — результат деления нуля на нуль.
Эта константа возвращается, когда результат операции неопределен.
119
Литература
1. Чарльз Петцольд, Программирование для Microsoft Windows на C#. Том1,2.
М.: Издательский отдел “Русская Редакция”,2002.
2. Эндрю Троелсен, С# и платформа .NET. Библиотека программиста.
СПб.: Питер, 2002.
120
Содержание
1.
Элементы языка .............................................................................................. 3
1.1 Комментарии ................................................................................................ 3
1.2 Идентификаторы ........................................................................................ 4
1.3 Ключевые слова........................................................................................... 5
1.4 Константы ....................................................................................................... 5
1.4.1 Целые знаковые .................................................................................... 5
1.4.2 Целые беззнаковые ............................................................................. 5
1.4.3 С плавающей точкой .......................................................................... 6
1.4.4 Символьные............................................................................................. 6
1.4.5 Строковые ................................................................................................ 7
1.5 Выражения ..................................................................................................... 7
1.6 Операции......................................................................................................... 7
1.6.1 Арифметические операции .............................................................. 8
1.6.2 Логические операции ......................................................................... 8
1.6.3 Операции отношения ......................................................................... 8
1.6.4 Операции присваивания ................................................................... 8
1.6.5 Операции инкремента и декремента .......................................... 9
1.6.6 Операции с массивами....................................................................... 9
1.6.7 Операции класса ................................................................................ 10
1.6.8 Побитовые операции ........................................................................ 10
1.6.9 Прочие операции ................................................................................ 10
1.6.10 Операции распределения памяти .............................................. 11
1.6.11 Приоритет и порядок выполнения операций ....................... 11
1.6.12 Арифметические преобразования.............................................. 12
1.7 Операторы .................................................................................................... 12
1.7.1 Оператор выражения ....................................................................... 12
1.7.2 Оператор метки ................................................................................... 12
1.7.3 Пустой оператор ................................................................................. 12
1.7.4 Составной оператор .......................................................................... 12
1.7.5 Управляющие конструкции ........................................................... 13
1.7.5.1 if..else ................................................................................................. 13
1.7.5.2 for ......................................................................................................... 13
1.7.5.3 while .................................................................................................... 14
1.7.5.4 goto ...................................................................................................... 14
1.7.5.5 switch .................................................................................................. 15
1.7.5.6 do .......................................................................................................... 15
1.7.5.7 foreach ................................................................................................ 16
1.7.5.8 return .................................................................................................. 17
1.7.5.9 break ................................................................................................... 17
1.7.5.10 continue ........................................................................................... 18
121
2.
Способы структурирования программы ............................................. 19
2.1 Логическая организация программы ............................................... 19
2.2 Физическая организация программы .............................................. 19
2.3 Объявления .................................................................................................. 20
2.3.1 Управление памятью......................................................................... 20
2.3.2 Типы данных ......................................................................................... 21
2.3.2.1 Структурные типы ........................................................................ 21
2.3.2.2 Ссылочные типы ........................................................................... 25
2.4 Классы ............................................................................................................ 27
2.4.1 Объявление ........................................................................................... 27
2.4.2 Члены класса........................................................................................ 29
2.4.2.1 Поля .................................................................................................... 29
2.4.2.2 Методы ............................................................................................... 32
2.4.2.3 Cвойства ............................................................................................ 35
2.4.2.4 Индексаторы ................................................................................... 37
2.4.2.5 Конструкторы.................................................................................. 39
2.4.2.6 Деструкторы .................................................................................... 40
2.4.3 Инкапсуляция....................................................................................... 41
2.4.4 Наследование ....................................................................................... 41
2.4.5 Полиморфизм ....................................................................................... 43
2.5 Структуры ..................................................................................................... 44
2.5.1 Объявление ........................................................................................... 44
2.5.2 Члены структуры ................................................................................ 45
2.5.3 Различия структур и классов........................................................ 45
2.6 Массивы ......................................................................................................... 47
2.6.1 Типы массива ....................................................................................... 47
2.6.2 Объявление массива ......................................................................... 47
2.6.3 Члены массива ..................................................................................... 48
2.7 Интерфейсы ................................................................................................. 48
2.7.1 Объявление ........................................................................................... 48
2.7.2 Члены интерфейса............................................................................. 49
2.7.3 Реализация интерфейса .................................................................. 50
2.7.4 Наследование ....................................................................................... 50
2.8 Перегрузка операций .............................................................................. 52
2.8.1 Унарные операции ............................................................................. 52
2.8.2 Бинарные операции .......................................................................... 52
2.9 Делегаты........................................................................................................ 54
2.9.1 Объявление ........................................................................................... 54
2.9.2 Одиночные делегаты ........................................................................ 55
2.9.3 Комбинированные делегаты ......................................................... 55
2.9.4 Использование делегатов .............................................................. 57
2.10 События.......................................................................................................... 58
122
2.10.1 Объявление ........................................................................................... 58
2.10.2 Генерация событий............................................................................ 58
2.11 Атрибуты........................................................................................................ 59
2.11.1 Типы данных допустимые в атрибутах .................................... 59
2.11.2 Объявление ........................................................................................... 60
2.11.3 Конструктор .......................................................................................... 60
2.11.4 Свойства ................................................................................................. 61
2.11.5 Применение атрибутов .................................................................... 61
2.11.5.1Применение атрибутов на уровне классов и методов...
.............................................................................................................. 61
2.11.5.2Применение атрибутов на уровне сборок ....................... 62
2.11.5.3Применение атрибутов на уровне модулей .................... 63
2.11.6 Специализированные атрибуты .................................................. 63
2.11.7 Определение собственного атрибута ....................................... 65
2.11.8 Использование атрибута AttributeUsageAttribute ............... 66
2.11.9 Доступ к информации, хранящейся в атрибутах ................ 67
2.11.9.1Получение одиночного атрибута ......................................... 67
2.11.9.2Получение списка однотипных атрибутов ...................... 68
2.11.9.3Получение списка разнотипных атрибутов .................... 69
2.12 Исключения.................................................................................................. 70
2.12.1 Генерация и перехват исключения ........................................... 71
2.13 Директивы препроцессора ................................................................... 73
3.
Встроенные элементы ................................................................................ 76
3.1 Класс System.Math.................................................................................... 76
3.1.1 Методы..................................................................................................... 76
3.1.2 Поля .......................................................................................................... 86
3.2 Класс System.Random ............................................................................. 87
3.2.1 Методы..................................................................................................... 87
3.3 Структура DateTime ................................................................................. 90
3.3.1 Методы..................................................................................................... 90
3.3.2 Свойства ................................................................................................. 91
3.4 Структура TimeSpan................................................................................. 95
3.4.1 Свойства ................................................................................................. 95
4.
Сообщения об ошибках компиляции .................................................. 98
123
Минеев С.А., Пряничников А.В., Кузьмина И.В.
Язык программирования
С#
_______________________________________________________
Подписано к печати
. Формат 60х84 116 .
Бумага писчая. Печать офсетная. Усл. печ. л. 1.5
Заказ
. Тираж 200 экз.
________________________________________________________
Нижегородский государственный университет им. Н.И.Лобачевского
603600 ГСП-20, Н. Новгород, просп. Гагарина, 23.
________________________________________________________
Типография ННГУ. 603000, Н. Новгород, ул. Б. Покровская, 37.
Download