1629295407-c61bfe4caba98380ea3e7cdae6295416 (846200), страница 68
Текст из файла (страница 68)
Это — единственноправильный вариант. Поскольку класс ExceptB выведен из класса ExceptA, catchинструкция для исключений типа ExceptB должна стоять перед инструкцией,Глава 13. Обработка исключительных ситуаций371предназначенной для перехвата исключений типа ExceptA. Точно так же catchинструкция для исключений класса Exception (который является базовым для всехисключений) должна стоять последней. Чтобы убедиться в этом, попробуйте переставитьcatch-инструкции в другом порядке.
Это приведет к ошибке при компиляции.Часто catch-инструкцию, определенную для исключений базового класса, успешноиспользуют для перехвата целой категории исключений. Предположим, вы создаете наборисключений для некоторого устройства. Если вывести все эти исключения из общегобазового класса, то приложения, которым не требуется подробные сведения о возникшейпроблеме, могли бы просто перехватывать исключение, настроенное на базовый класс,избегнув тем самым ненужного дублирования кода.Использование ключевых слов checkedи uncheckedВ C# предусмотрено специальное средство, которое связано с генерированиемисключений, связанных с переполнением в арифметических вычислениях.
Как вы знаете, внекоторых случаях при вычислении арифметических выражений получается результат,который выходит за пределы диапазона, определенного для типа данных в выражении. Вэтом случае говорят, что произошло переполнение результата. Рассмотрим, например,такой фрагмент программы:byte a, b, result;a = 127;b = 127;result = (byte)(a * b);Здесь произведение значений a и b превышает диапазон представления значенийтипа byte.
Следовательно, результат вычисления этого выражения вызвал переполнениедля типа переменной result.C# позволяет управлять генерированием исключений при возникновениипереполнения с помощью ключевых слов checked и unchecked. Чтобы указать, чтонекоторое выражение должно быть проконтролировано на предмет переполнения,используйте ключевое слово checked. А чтобы проигнорировать переполнение,используйте ключевое слово unchecked. В последнем случае результат будет усечен так,чтобы его тип соответствовал типу-результату выражения.Ключевое слово checked имеет две формы. Одна проверяет конкретное выражениеи называется операторной checked-формой. Другая же проверяет блок инструкций.checked(expr)checked {// Инструкции, подлежащие проверке.}Здесь expr — выражение, которое необходимо контролировать. Если значениеконтролируемоговыраженияпереполнилось,генерируетсяисключениетипаOverflowException.Ключевое слово unchecked имеет две формы.
Одна из них — операторная форма,которая позволяет игнорировать переполнение для заданного выражения. Втораяигнорирует переполнение, которое возможно в блоке инструкций.unchecked(expr)372Часть I. Язык C#unchecked {// Инструкции, для которых переполнение игнорируется.}Здесь expr — выражение, которое не проверяется на предмет переполнения.
Вслучае переполнения это выражение усекается.Рассмотрим программу, которая демонстрирует использование как слова checked,так и слова unchecked.// Использование ключевых слов checked и unchecked.using System;class CheckedDemo {public static void Main() {byte a, b;byte result;a = 127;b = 127;try {result = unchecked((byte) (a * b) );Console.WriteLine("Unchecked-результат: " + result);result = checked((byte)(a * b));// Эта инструкция// вызывает исключение.Console.WriteLine("Checked-реэультат: " +result);// Инструкция не будет// выполнена.}}}catch(OverflowException exc) {// Перехватываем исключение.Console.WriteLine(exc);}При выполнении этой программы получаются такие результаты:Unchecked-результат: 1System.OverflowException: Arithmetic operation resulted in anoverflow.at CheckedDemo.Main()Как видите, результат непроверяемого выражения усекается.
В случае разрешенияпроверки переполнения было бы сгенерировано исключение.В предыдущей программе было продемонстрировано использование ключевых словchecked и unchecked для одного выражения. На примере следующей программыпоказано, как можно избежать переполнения при выполнении блока инструкций.// Использование ключевых слов checked и unchecked// для блоков инструкций.using System;class CheckedBlocks {public static void Main() {byte a, b;byte result;Глава 13. Обработка исключительных ситуаций373a = 127;b = 127;try {unchecked {a = 127;b = 127;result = unchecked((byte)(a * b));Console.WriteLine("Unchecked-результат: " + result);a = 125;b = 5;result = unchecked((byte)(a * b));Console.WriteLine("Unchecked-реэультат: " + result);}}}}checked {a = 2;b = 7;result = checked((byte)(a * b)); // Все в порядке.Console.WriteLine("Checked-результат: " + result);a = 127;b = 127;result = checked((byte)(a * b)); // Здесь должно// быть сгенерировано// исключение.Console.WriteLine("Checked-результат: " +result);// Эта инструкция не// выполнится.}catch(OverflowException exc) {// Перехватываем исключение.Console.WriteLine(exc);}Вот как выглядят результаты выполнения этой программы:Unchecked-результат: 1Unchecked-результат: 113Checked-результат: 14System.OverflowException: Arithmetic operation resulted in anoverflow.
at CheckedBlocks.Main()Как видите, при выполнении unchecked-блока результат вычисления выраженияпри наличии переполнения усекается. При возникновении переполнения в checked-блокегенерируется исключение.Управление генерированием исключений с помощью ключевых слов checked илиunchecked может быть полезным в том случае, когда checked/unchecked-статуспереполнения определяется использованием соответствующей опции компилятора инастройкой самой среды выполнения. Таким образом, для некоторых типов программлучше всего явно задавать статус контроля переполнения.374Часть I. Язык C#Полныйсправочник поГлава 14Использование средствввода-выводаСсамого начала книги мы использовали часть C#-системы ввода-вывода — методConsole.WriteLine(), но не давали подробных пояснений по этому поводу.Поскольку C#-система ввода-вывода построена на иерархии классов, то ее теорию и деталиневозможно освоить, не рассмотрев сначала классы, наследование и исключения.
Теперьнастало время для подробного изучения C#-средств ввода-вывода. Поскольку в C#используется система ввода-вывода и классы, определенные средой .NET Framework, в этутему включено рассмотрение в общих чертах системы ввода-вывода .NET-среды.В этой главе рассматриваются средства как консольного, так и файлового вводавывода. Необходимо сразу отметить, что C#-система ввода-вывода — довольно обширнаятема, и здесь описаны лишь самые важные и часто применяемые средства.Организация C#-системы ввода-выводаC#-программы выполняют операции ввода-вывода посредством потоков.
Поток(stream) — это абстракция, которая либо синтезирует информацию, либо потребляет ее.Поток связывается с физическим устройством с помощью C#-системы ввода-вывода.Характер поведения всех потоков одинаков, несмотря на различные физические устройства,с которыми они связываются. Следовательно, классы и методы ввода-вывода можноприменить ко многим типам устройств. Например, методы, используемые для записиданных на консольное устройство, также можно использовать для записи в дисковый файл.Байтовые и символьные потокиНа самом низком уровне все C#-системы ввода-вывода оперируют байтами. И этологично, поскольку многие устройства при выполнении операций ввода-выводаориентированы на байты.
Однако для человека привычнее оперировать символами.Вспомните, что в C# char — это 16-разрядный тип, a byte — 8-разрядный. Если выиспользуете набор символов ASCII, то в преобразовании типов char и byte нет ничегосложного: достаточно проигнорировать старший байт char-значения.
Но такой подход несработает для остальных Unicode-символов, которым необходимы оба байта. Такимобразом, байтовые потоки не вполне подходят для обработки текстового (ориентированногона символы) ввода-вывода. Для решения этой проблемы в C# определен ряд классов,которые преобразуют байтовый поток в символьный, выполняя byte-char- и charbyte-перевод автоматически.Встроенные потокиТремя встроенными потоками, доступ к которым осуществляется через свойстваConsole.In, Console.Out и Console.Error, могут пользоваться все программы,работающие в пространстве имен System. Свойство Console.Out относится кстандартному выходному потоку. По умолчанию это консоль. Например, при вызове методаConsole.WriteLine() информация автоматически передается в поток Console.Out.Свойство Console.In относится к стандартному входному потоку, источником которогопо умолчанию является клавиатура.
Свойство Console.Error относится к ошибкам встандартном потоке, источником которого также по умолчанию является консоль. Однакоэти потоки могут быть перенаправлены на любое совместимое устройство ввода-вывода.Стандартные потоки являются символьными. Следовательно, эти потоки считывают изаписывают символы.376Часть I. Язык C#Классы потоковВ C# определены как байтовые, так и символьные классы потоков. Однакосимвольные классы потоков в действительности представляют собой оболочки, которыепреобразуют базовый байтовый поток в символьный, причем любое преобразованиевыполняется автоматически.