- •1 Основные сведения о C#
- •1.1 Особенности языка
- •1.2 Типы данных
- •1.3 Переменные
- •1.4 Константы (литералы)
- •1.5 Операторы, используемые при построении выражений
- •1.6 Класс Object
- •1.7 Класс Math
- •1.8 Класс Convert
- •1.9 Пространство имен
- •1.10 Типы, допускающие значение null
- •2 Операторы и конструкции С#
- •2.1 Операторы присваивания
- •2.2 Приведение типов
- •2.3 Операторы инкремента и декремента
- •2.4 Операторные скобки {}
- •2.5 Условный оператор if
- •2.6 Логические операторы “И” и “ИЛИ”
- •2.7 Условный оператор ? :
- •2.8 Оператор выбора switch и оператор прерывания break
- •2.9 Оператор цикла for
- •2.10 Оператор цикла while
- •2.11 Оператор цикла do...while
- •2.12 Операторы прерываний break (для циклов) и continue
- •2.13 Оператор new
- •2.14 Массивы
- •2.14.1 Одномерные массивы
- •2.14.2 Многомерные массивы
- •2.14.3 Ступенчатые массивы
- •2.14.4 Работа с массивами как с объектами
- •2.15 Оператор цикла foreach
- •2.16 Строки
- •2.17 Перечисления
- •2.18 Обработка исключений
- •2.18.1 Класс Exception и стандартные исключения
- •2.18.2 Блок try...catch
- •2.18.3 Блок try...finally
- •2.18.4 Блок try...catch...finally
- •2.18.5 Оператор throw
- •3 Классы. Основные понятия
- •3.1 Общая схема
- •3.2 Спецификаторы доступа
- •3.3 Поля
- •3.4 Создание объекта и доступ к его членам
- •3.5 Методы
- •3.6 Перегрузка методов
- •3.7 Конструкторы
- •3.8 Деструкторы
- •3.9 Инициализаторы объектов
- •3.10 Свойства
- •3.11 Индексаторы
- •4 Классы. Расширенное использование
- •4.1 Статические классы и члены классов
- •4.2 Наследование
- •4.2.1 Наследование и конструкторы
- •4.2.2 Переопределение членов класса
- •4.3 Полиморфизм
- •4.3.1 Виртуальные методы
- •4.3.2 Абстрактные классы и члены классов
- •4.3.3 Операторы as и is
- •4.3.4 Модификатор sealed
- •5 Интерфейсы
- •6 Работа с файлами
- •6.1 Класс File
- •6.2 Работа с файлами как с потоками
- •6.2.1 Класс FileStream
- •6.2.2 Класс StreamReader
- •6.2.3 Класс StreamWriter
- •6.2.4 Класс BinaryReader
- •6.2.5 Класс BinaryWriter
поля для хранения значения, т.к. такое поле выделяется для свойства автоматически. Пример поля:
class MyClass
{
public int p { get; set; }
}
На значения автоматически реализуемых свойств нельзя наложить никаких ограничений, их нельзя сделать “только для чтения” или “только для записи”1. Поэтому применение таких свойств достаточно ограничено.
3.11 Индексаторы
Индексаторы позволяют рассматривать объект класса как массив, т.е. обращаться к его элементам с использованием индексов, указываемых в квадратных скобках.
Формальная структура описания индексатора имеет вид:
[<доступ>] <тип> this[<список индексов>] {get {<код метода достура get>} set {<код метода достура set>}}
где:
<список индексов> – набор индексов, перечисленных через запятую, каждый из которых имеет структуру:
<тип> <идентификатор>;
чаще всего <тип> является целым, хотя может быть любым;
<код метода достура get> – код, определяющий действия, выполняемые при запросе значения индексатора и использующий индексы, определенные в
<список индексов>;
<код метода достура set> – код, определяющий действия, выполняемые при установке значения индексатора и использующий индексы, определенные в
<список индексов>.
Метод доступа get должен содержать оператор return, определяющий зна-
чение, возвращаемое методом get при запросе значения индексатора.
Метод доступа set имеет неявно заданный параметр value, который позволяет указать значение, присваиваемое индексатору.
Как и свойство, индексатор обычно связан с полем, имеющим спецификатор доступа private или protected. В большинстве случаев, данное поле является массивом типа <тип>, имеющим количество размерностей, равное количеству па-
раметров в <список индексов>.
1 Подразумевается, что нельзя пропустить метод get или set. Однако это можно реализовать используя спецификаторы доступа для этих методов
59
Пример: класс, имеющий одномерный индексатор и возвращающий значение -1, если происходит обращение к элементу с недопустимым индексом.
class MyClass
{
private int[] _mas; public MyClass(int count)
{
if (count > 0)
_mas = new int[count]; else
_mas = new int[0];
}
public int this[int index]
{
get
{
return (index >= 0 && index < _mas.Length) ? _mas[index] : -1;
}
set
{
if (index >= 0 && index < _mas.Length) _mas[index] = value;
}
}
}
MyClass cl = new MyClass(10); cl[5] = 7;
int i1 = cl[4]; // i1 = 0; int i2 = cl[5]; // i2 = 7; int i3 = cl[-1]; // i3 = -1; int i4 = cl[10]; // i4 = -1;
Пример: класс описывающий шахматную доску и имеющий двухмерный индексатор с индексами типа char (буквы от 'a' до 'h') и типа byte (цифры от 1 до 8) возвращающий тип фигуры, стоящей на заданной клетке, признак пустой клетки или значение ошибки, если происходит обращение к элементу с недопустимым индексом.
enum ChessFigure {King,Queen,Rook,Bishop,Knight,Pawn,Empty,Error};
class MyClass
{
private string s = "abcdefgh"; private ChessFigure[,] _mas; public MyClass()
{
_mas = new ChessFigure[8,8]; for (int i=0; i<8; i++)
for (int j=0; j<8; j++) _mas[i,j] = ChessFigure.Empty;
60
}
public ChessFigure this[char c,byte n]
{
get
{
int i = s.IndexOf(c);
if (i >= 0 && n >= 1 && n <= 8) return _mas[i,n-1];
else
return ChessFigure.Error;
}
set
{
int i = s.IndexOf(c);
if (i >= 0 && n >= 1 && n <= 8) _mas[i,n-1] = value;
}
}
}
MyClass cl = new MyClass(); cl['b',3] = ChessFigure.Queen;
ChessFigure f1 = cl['b',3]; // f1 = Queen ChessFigure f2 = cl['e',8]; // f2 = Empty ChessFigure f3 = cl['k',2]; // f3 = Error ChessFigure f4 = cl['h',0]; // f4 = Error
Как и у свойства, у индексатора могут отсутствовать методы get или set для создания индексаторов “только для записи” или “только для чтения” соответственно.
Индексатор может быть перегружен. В этом случае при обращении используется тот из индексаторов, у которого индексы наиболее подходят заданным. Поэтому при перегрузке индексаторов количество и/или тип индексов должны отличаться.
Пример: класс, позволяющий получить либо доступ к заданному элементу матрицы, либо сумму элементов строки заданной матрицы с помощью индексаторов. Считать, что значение элемента или суммы элементов строки при неправильном задании индекса равно -1.
class MyClass
{
private int[,] _mas;
public MyClass(int countRow,int countCol)
{
if (countRow > 0 && countCol > 0) _mas = new int[countRow,countCol];
else
_mas = new int[0,0];
}
public int this[int indexRow,int indexCol]
{
get
{
61
if (indexRow >= 0 && indexRow < _mas.GetLength(0) && indexCol >= 0 && indexCol < _mas.GetLength(1))
return _mas[indexRow,indexCol]; else
return -1;
}
set
{
if (indexRow >= 0 && indexRow < _mas.GetLength(0) && indexCol >= 0 && indexCol < _mas.GetLength(1))
_mas[indexRow,indexCol] = value;
}
}
public int this[int indexRow]
{
get
{
if (indexRow > 0 && indexRow < _mas.GetLength(0))
{
int sum=0;
for (int i=0; i < _mas.GetLength(1); i++) sum += _mas[indexRow,i];
return sum;
}
else
return -1;
}
}
}
MyClass cl = new MyClass(3,3);
for (int i=0; i<3; i++) |
|
|
||
for (int j=0; j<3; j++) |
|
|||
cl[i,j] = i*3+j+1; |
|
|
||
int i1 |
= cl[1,0]; // i1 = |
4 |
||
int i2 |
= cl[3,3]; |
// i2 = |
-1 |
|
int i3 |
= cl[1]; |
// i3 |
= |
15 |
int i4 |
= cl[4]; |
// i4 |
= |
-1 |
62