Г. Шилдт - С#4.0 Полное руководство (1160795), страница 136
Текст из файла (страница 136)
Небезопасный код, указатели, обнулявыые типы и разные каочавыв слова 697 Свойство )(а1пе возвращает экземпляр обнуляемого объекта, для которого оно вызывается. Если же попытаться получить с помощью этого свойства значение пустой переменной, то в итоге будет сгенерировано исключение нуягеы. 1пча11боре гаслопкхсерс1 оп. Кроме того, значение экземпляра обнуляемого объекта можно получить путем приведения к его базовому типу.
В следующей программе демонстрируется основной механизм обращения с обнуляемым типом. О Продемонстрировать применение обнуляемого типа. иягпч Зуясет; с1аяя Нп11аъгеоеио ( ясасгс чона На1п() ( гпс? сопля = пп111 11(сопля.наяуа1пе) сопяо1е.игггеьгпе("переменная сопля имеет следуьзцее значение: сопля.уа1пе); е1яе Сопяо1е.иг(сеъгпе("У переменной сопля отсутствует значение"); сопля = 100; га(сопля.наяуа1пе) Сопяо1е.нг1сеъгпе("переменная сопля имеет следукщее значение: соопг.уа1пе); е1яе сапяо1е.хг1геьгпе("у переменной сопля отсутствует значение")1 ) ) Вот к какому результату приводит выполнение этой программы.
у переменной сопля отсутствует значение Переменная сопля имеет следупцее значение: 100 Применение обнуйяемых объектов в выражениях Обнуляемый объект может использоваться в тех выражениях, которые являются действительными для его базового типа. Более того, обнуляемые объекты могут сочетаться с необнуляемыми объектами в одном выражении. И это вполне допустимо благодаря предопределенному преобразованию базового типа в обнуляемый. Когда обнуляемые и необнуляемые типы сочетаются в одной операции, ее результатом становится значение обнуляемого типа. В приведенной ниже программе демонстрируется применение обнуляемых типов в выражениях. // Использовать обнуляемые обьекты в выражениях. пв1пэ ЗУЯГец1; с1аяя Нп11аЬ1ебеыо ( ягагьс лога Нагл 698 Часть (.
Язык С() гпс? соипс = пи11) гпг? геяи1ц = пи11) 1пс гпсг = 10) // переменная гпсг не является обнуляемой переменная геяи1г содержит пустое значение, // переменная оказывается соипс пустой. геяи1г = соипг + гпсг; 1Г (геяи1с.яаяча1ие) Сопяо1е Иг1сеъгпе("Переменная геяи1Г имеет следуюцее значение: геяи1г.уа1ие)) е1яе Сопяо1е.иггсеььпе("У переменной геяи1С отсутствует значение" )) Теперь переменная соипс получает свое значение, и иозтому уу переменная геяи1Г будет содержать конкретное значение. соипс = 100) геяи1Г = соипс ь гпсг) гц(геяи1ц.наяиа1ие) Сопяо1е.нг1сеъгпе("Переменная геяи10 имеет следупцее значение: ге яи1г .
иа1ие )," е1яе Сопяо1е.иггсеъъпе(ну переменной геяи1Г отсутствует значение"); При выполнении этой программы получается следующий результат. У переменной геяи1С отсутствует значение Переменная геяи1Ц имеет следуцж)ее значение: 110 Оператор?? Попытка преобразовать обнуляемый объект в его базовый тип путем приведения типов обычно приводит к генерированию исключения эуясец). 1пиа11с(Орегас1опехсерс1оп, если обнуляемый объект содержит пустое значение. Это может произойти, например, в том случае, если значение обнуляемого объекта присваивается переменной его базового типа с помощью приведения типов.
Появления данного исключения можно избежать, если воспользоваться оператором ??, называемым нулеобъединяюц(им операторам. Этот оператор позволяет указать значение, которое будет использоваться по умолчанию, если обнуляемый объект содержит пустое значение. Он также исключает потребность в приведении типов. Ниже приведена общая форма оператора??. обнуляемнй объект ?? значение по умолчанию Если обнуляемый объект содержит конкретное значение, то результатом операции?? будет именно это значение.
В противном случае результатом операции?? окажется значение по умолчанию. Например, в приведенном ниже фрагменте кода переменная )за1апсе содержит пустое значение. Вследствие этого переменной сиггепсВа1апсе присваивается значение О . О, используемое по умолчанию, и тем самым устраняется причина для генерирования исключения. Глава 20. Небезопасный код, указатели, обнуляемые типы и разные ключевые слова 699 СопЫе? Ьа1апсе = пп11; СопЫе спггепСВа1апсе; спггепСВа1апсе = Ьа1апсе ?? 0.0; В следующем фрагменте кода переменной Ьа1апсе присваивается значение 123.75.
СопЫе? Ьа1апсе = 123.75; СопЫе спггепСВа1апсе; спггепСВа1апсе = Ьа1апсе ?? 0.0; Теперь переменная спггепсна1апсе содержит значение 123. 75 переменной Ьа1апсе. И еще одно замечание: выражение в правой части оператора ?? вычисляется только в том случае, если выражение в левой его части не содержит значение. Этот факт демонстрируется в приведенной ниже программе. 7? Применение оператора ?? оз1пэ Бузсеи; с1азз Нп11аЬ1еоезо2 ( // Возвратить нулевой остаток. зСагьс г)опЬ1е СеСЕегоВа1() ( Сопзо1е.нгааеььпе("В метоле оеСЕегоВа1().") гесьгп 0.0; ) агаС1о уоьо Мази () ( СопЬ1е? Ьа1апсе = 123.75; оопЬ1е спггепСВа1апсе; О Здесь метод Сегзегова1() не вызывается, поскольку // переменная Ьа1апсе содерзит конкретное значение. спггепСВа1апсе = Ьа1апсе ?? оеСЕегоВа1(); Сопзо1е.нг1Сеъьпе(спггепСВа1апсе) В этой программе метод СеСЕегона1 () не вызывается, поскольку переменная Ьа1апсе содержит конкретное значение.
Как пояснялось выше, если выражение в левой части оператора ?? содержит конкретное значение, то выражение в правой его части не вычисляется. Обнуляемые объекты, операторы отношения и логические операторы Обнуляемые объекты могут использоваться в выражениях отношения таким же образом, как и соответствующие объекты необнуляемого типа. Но они должны подчиняться следующему дополнительному правилу: когда два обнуляемых объекта сравНнааЮтоя В ОПЕрацняХ СраВНЕНИя <, >, <= ИЛИ >сь тО ИХ рЕЗуЛЬтат будЕт ЛОЖНЫМ, ЕСЛИ любой из обнуляемых объектов оказывается пустым, т.е.
содержит значение пп11. В качестве примера рассмотрим следующий фрагмент кода. 700 Часть (. Язык С() Ьуге? 1онег = 16? Ьусе? нррет = пн11; Здесь переменная 1онег определена, а переменная оррег не определена. 1Г(1онет < иррет( // ложно 1 В данном случае проверка того, что значение одной переменой меньше значения другой, дает ложный результат.
Хотя это и не совсем очевидно, как, впрочем, и следующая проверка противоположного характера. 1Г(1онег > оррет( // .. также ложно! Следовательно, если один или оба сравниваемых обнуляемых объекта оказываются пустыми, то результат их сравнения всегда будет ложным. Это фактически означает, что пустое значение (пп11) не участвует в отношении порядка. Тем не менее с помощью операторов == и ! = можно проверить, содержит ли обнуляемый объект пустое значение. Например, следующая проверка вполне допустима и дает истинный результат.
тг(нррег == пн11( Если в логическом выражении участвуют два объекта типа Ьоо1?, то его результат может иметь одно из трех следующих значений: С где (истинное), йа1яе (ложное) или пп11 (неопределенное). Ниже приведены результаты применения логических операторов ь и ( к объектам типа Ьоо1?. Р(0 Ряс И наконец, если логический оператор ! применяется к значению типа Ьоо1?, которое является пустым (пп11), то результат этой операции будет неопределенным (пп11). Частичные типы Начиная с версии 2.0, в С(( появилась возможность разделять определение класса, структуры или интерфейса на две или более части с сохранением каждой из них в отдельном файле.
Это делается с помощью контекстного ключевого слова рагсьа1. Все эти части объединяются вместе во время компиляции программы. Если модификатор раггаа1 используется для создания частичного типа, то он принимает следующую общую форму: рагста1 тип имл типа ( где иьгд типа обозначает имя класса, структуры или интерфейса, разделяемого на ча- сти.
Каждая часть получающегося частичного типа должна указываться вместе с моди- фикатором рагсуа1. Сгпе йа1яе пп11 пп11 пи11 пп11 пп11 сгпе га1яе пп11 Сгпе пп11 Сгне пп11 пп11 пп11 га1яе пп11 йа1яе пп11 Глава 20. Небезопасный код, указатели, обнуляемые типы и разные ключевые слова 701 рассмотрим пример разделения простого класса, содержащего координаты Ху, на три отдельных файла. Ниже приведено содержимое первого файла. рагтта1 с1авв Ху риЫ1с Ху(1пг а, 1пт Ы ( Х= а; Х=Ь; ) Далее следует содержимое второго файла.
рагвта1 с1авв ХУ ( роЬ11с ьпг Х ( лещ веЮ ) И наконец, содержимое третьего файла. раггта1 с1авв ХУ ( рнЫьс ьпт У ( Чем вею ) В приведенном нихсе файле исходного текста программы демонстрируется применение класса Ху. Продемонстрировать определения частичного класса. пвьпд Яувсеьс с1авв тевп ( вгаг1с тото Маьп() ( ХУ ху = пеи ХУ(1, 2)г Сопво1е .Игттеюпе (ху.Х + ", " т ху. у); ) ) Для того чтобы воспользоваться классом Ху, необходимо включить в компиляцию все его файлы. Так, если файлы класса Ху называются ху1. се, ху2. се и хуЗ .
се, а класс тезс содержится в файле сенс. сз, то для его компиляции достаточно ввести в командной строке следующее. свс Савв.св ху1.св ху2.св хуз.св И последнее замечание: в С() допускаются частичные обобщенные классы. Но параметры типа в объявлении каждого такого класса должны совпадать с теми, что указываются в остальных его частях. Частичные методы Как пояснялось в предыдущем разделе, с помощью модификатора рагкьа1 можно создать класс частичного типа.
Начиная с версии 3.0, в СФ появилась возможность иатользовать этот модификатор и для создания часпгичного лен)ода в элементе данных частичного типа. Частичный метод объявляетог в одной его части, а реализуется в другой. Следовательно, с помощью модификатора раггьа1 можно отделить объявление метода от его реализации в частичном классе или структуре. 702 Часть!. Язык С() Главная особенность частичного метода заключается в том, что его реализация не требуется! Если частичный метод не реализуется в другой части класса или структуры, то все его вызовы молча игнорируются. Это дает возможность определить, но не востребовать дополнительные, хотя и не обязательные функции класса.
Если эти функции не реализованы, то они просто игнорируются. Ниже приведена расширенная версия предыдущей программы, в которой создается частичный метод БЬон () . Этот метод вызывается другим методом, ЯЬонХХ () . Ради удобства все части класса ХХ представлены в одном файле, но они могут быть распределены по отдельным файлам, как было показано в предыдущем разделе. // Продемонстрировать применение частичного метода. ся1пЧ Буясеи; рагсга1 с1аяя ХХ ( рпЫгс ХХ(ьпс а, 1пя Ы ( Х = аг Х = Ь) // Опънвить частичный метод.