Чтение онлайн

на главную - закладки

Жанры

Полное руководство. С# 4.0
Шрифт:

В этом выражении переменная t и значения 2 и 3 относятся к типу int, но в ней присутствует также объект типа Nybble. Оба типа оказываются совместимыми благо даря неявному преобразованию типа Nybble в тип int. В данном случае остальная часть выражения относится к типу int, поэтому объект а преобразуется в тип int с помощью своего метода преобразования.

А благодаря преобразованию типа int в тип Nybble значение типа int может быть присвоено объекту типа Nybble. Например, в следующей строке из приведенной выше программы: а = 19;

сначала выполняется оператор преобразования типа int в тип Nybble. Затем созда ется новый объект типа Nybble, в котором сохраняются 4 младших разряда целого значения 19, а по существу, число 3, поскольку значение 19 превышает диапазон пред ставления чисел для типа Nybble. Далее этот объект присваивается

переменной эк земпляра а. Без операторов преобразования подобные выражения были бы просто недопустимы.

Кроме того, преобразование типа Nybble в тип Nybble используется в цикле for. Без такого преобразования организовать столь простой цикл for было бы просто не возможно.

ПРИМЕЧАНИЕ В качестве упражнения попробуйте создать вариант полубайтового типа Nybble, предотвращающий переполнение, если присваиваемое значение оказывается за пределами допустимого диапазона чисел. Для этой цели лучше всего сгенерировать исключение. (Подробнее об исключениях — в главе 13.)

ГЛАВА 10. Индексаторы и свойства

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

Как вам должно быть уже известно, индексирование массива осуществляется с помощью оператора []. Для создаваемых классов можно определить оператор [], но с этой целью вместо операторного метода создается индексатор, который позволяет индексировать объект, по добно массиву. Индексаторы применяются, главным об разом, в качестве средства, поддерживающего создание специализированных массивов, на которые накладывается одно или несколько ограничений. Тем не менее индексато ры могут служить практически любым целям, для которых выгодным оказывается такой же синтаксис, как и у масси вов. Индексаторы могут быть одно- или многомерными. Рассмотрим сначала одномерные индексаторы. Создание одномерных индексаторов

Ниже приведена общая форма одномерного индексатора: тип_элемента this[int индекс] { // Аксессор для получения данных. get { // Возврат значения, которое определяет индекс. } // Аксессор для установки данных. set { // Установка значения, которое определяет индекс. } }

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

В теле индексатора определены два аксессора (т.е. средства доступа к данным): get и set. Аксессор подобен методу, за исключением того, что в нем не объявляется тип возвращаемого значения или параметры. Аксессоры вызываются автоматически при использовании индексатора, и оба получают индекс в качестве параметра. Так, если индексатор указывается в левой части оператора присваивания, то вызывается аксессор set и устанавливается элемент, на который указывает параметр индекс. В противном случае вызывается аксессор get и возвращается значение, соответствующее параметру индекс. Кроме того, аксессор set получает неявный параметр value, содержащий значение, присваиваемое по указанному индексу.

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

класса, а доступ к нему осуществляется только с помо щью индексатора. При таком подходе исключается любая попытка получить доступ к массиву за его границами, причем эта попытка пресекается без катастрофических последствий для программы. А поскольку в классе FailSoftArray используется ин дексатор, то к массиву можно обращаться с помощью обычной формы записи. // Использовать индексатор для создания отказоустойчивого массива. using System; class FailSoftArray { int[] a; // ссылка на базовый массив public int Length; // открытая переменная длины массива public bool ErrFlag; // обозначает результат последней операции // Построить массив заданного размера. public FailSoftArray(int size) { a = new int[size]; Length = size; } // Это индексатор для класса FailSoftArray. public int this[int index] { // Это аксессор get. get { if(ok(index)) { ErrFlag = false; return a[index]; } else { ErrFlag = true; return 0; } } // Это аксессор set. set { if(ok(index)) { a[index] = value; ErrFlag = false; } else ErrFlag = true; } } // Возвратить логическое значение true, если // индекс находится в установленных границах. private bool ok(int index) { if(index >= 0 & index < Length) return true; return false; } } // Продемонстрировать применение отказоустойчивого массива. class FSDemo { static void Main { FailSoftArray fs = new FailSoftArray(5); int x; // Выявить скрытые сбои. Console.WriteLine("Скрытый сбой."); for(int i=0; i < (fs.Length * 2); i++) fs[i] = i*10; for(int i=0; i < (fs.Length * 2); i++) { x = fs[i]; if(x != -1) Console.Write(x + " "); } Console.WriteLine; // А теперь показать сбои. Console.WriteLine("\nСбой с уведомлением об ошибках."); for (int i=0; i < (fs.Length * 2); i++) { fs[i] = i * 10; if(fs.ErrFlag) Console.WriteLine("fs[" + i + "] вне границ"); } for(int i=0; i < (fs.Length * 2); i++) { x = fs[i]; if(!fs.ErrFlag) Console.Write(x + " "); else Console.WriteLine("fs[" + i + "] вне границ"); } } }

Вот к какому результату приводит выполнение этой программы. Скрытый сбой. 0 10 20 30 40 0 0 0 0 0 Сбой с уведомлением об ошибках. fs[5] вне границ fs[6] вне границ fs[7] вне границ fs[8] вне границ fs[9] вне границ 0 10 20 30 40 fs[5] вне границ fs[6] вне границ fs[7] вне границ fs[8] вне границ fs[9] вне границ

Индексатор препятствует нарушению границ массива. Внимательно проанализи руем каждую часть кода индексатора. Он начинается со следующей строки. public int this[int index] {

В этой строке кода объявляется индексатор, оперирующий элементами типа int. Ему передается индекс в качестве параметра index. Кроме того, индексатор объявля ется открытым (public), что дает возможность использовать этот индексатор в коде за пределами его класса.

Рассмотрим следующий код аксессора get. get { if(ok(index)) { ErrFlag = false; return a[index]; } else { ErrFlag = true; return 0; } }

Аксессор get предотвращает ошибки нарушения границ массива, проверяя в пер вую очередь, находится ли индекс в установленных границах. Эта проверка границ вы полняется в методе ok, который возвращает логическое значение true, если индекс правильный, а иначе — логическое значение false. Так, если указанный индекс на ходится б установленных границах, то по этому индексу возвращается соответствую щий элемент. А если индекс оказывается вне установленных границ, то никаких опе раций не выполняется, но в то же время не возникает никаких ошибок переполнения. В данном варианте класса FailSoftArray переменная ErrFlag содержит результат каждой операции. Ее содержимое может быть проверено после каждой операции на предмет удачного или неудачного выполнения последней. (В главе 13 будет представ лен более совершенный способ обработки ошибок с помощью имеющейся в C# под системы обработки исключительных ситуаций, а до тех пор можно вполне обойтись установкой и проверкой признака ошибки.)

А теперь рассмотрим следующий код аксессора set, предотвращающего ошибки нарушения границ массива. set { if(ok(index)) { a[index] = value; ErrFlag = false; } else ErrFlag = true; }

Если параметр index метода ok находится в установленных пределах, то соот ветствующему элементу массива присваивается значение, передаваемое из параметра value. В противном случае устанавливается логическое значение true переменной ErrFlag. Напомним, что value в любом аксессорном методе является неявным пара метром, содержащим присваиваемое значение. Его не нужно (да и нельзя) объявлять отдельно.

Поделиться:
Популярные книги

Свадьба по приказу, или Моя непокорная княжна

Чернованова Валерия Михайловна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Свадьба по приказу, или Моя непокорная княжна

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Вадбольский

Никитин Юрий Александрович
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Вадбольский

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания

Таня Гроттер и магический контрабас

Емец Дмитрий Александрович
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Таня Гроттер и магический контрабас

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

Кодекс Крови. Книга ХI

Борзых М.
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХI

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Возвышение Меркурия. Книга 16

Кронос Александр
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 16

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Потусторонний. Книга 1

Погуляй Юрий Александрович
1. Господин Артемьев
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Потусторонний. Книга 1