Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 130
Текст из файла (страница 130)
гевп1Г = сопле + 1псщ 1Т(гево1Г.Навуа1пе) Сопво1е.Иггсеъьпе("Переменная гевп1Г имеет " т "следующее значение: " т гевп1г.уа1пе)т е1ве Сопво1е.нг1сеъ1пе("Переменная гевп1Г не имеет значение") // Теперь переменная сопле получает свое значение, и // поэтому переменная гево1Г будет содержать // конкретное значение. соопс = 100? гевп1Г = соипс + гпсг; 1Т(гевч1Г.Навча1ое) Сопво1е.Иггсевапе("Переменная гевп1Г имеет " т "следующее значение: " + гево1с.уа1не); е1ве Сопво1е.нггсеъапе("Переменная геви1Г не имеет значения")) При выполнении этой программы получается следующий результат: Переменная гево1Г не имеет значение Переменная гево1Г имеет следующее значение: 110 Глава 20.
Небезопасный код, указатели, обиуллеыые типы и разные ключевые слова 675 ОператОр 7'? Попытка преобразовать обнуляемый объект в его базовый тип путем приведения типов обычно приводит к генерированию исключения Бузсею. 1пчв1160регасйопехсерсйоп, если обнуляемый объект содержит пустое значение. Это может произойти, например, в том случае, если значение обнуляемого объекта присваивается переменной его базового типа с помощью приведения типов. Появления данного исключения можно избежать, если воспользоваться оператором ??, называемым нулеобвединлюы(им оиерал)орам.
Этот оператор позволяет указать значение, которое будет использоваться по умолчанию, если обнуляемый объект содержит пустое значение. Он также исключает потребность в приведении типов. Ниже приведена общая форма оператора? 7. обнуллеьтмй объект ?? значение по умолчанию Если обнуллеммй объект содержит конкретное значение, то результатом операции ?? будет именно это значение.
В противном случае результатом операции ".. окажется значение по умолчанию. Например, в приведенном ниже фрагменте кода переменная Ьа1апсе содержит пустое значение. Вследствие этого переменной снггепсВа1впсе присваивается значение О. О, используемое по умолчанию, и тем самым устраняется причина для генерирования исключения. т(очЬ1в? Ьв1впсв = пв117 боиЬ1в снггвпСВв1впсвт спггвпСВв1впсв = Ьв1впсе ?? 0.07 В следующем фрагменте кода переменной Ьа1апсе присваивается значение 123. 75: бонЬ1е? Ьв1впсе = 123.75) бонЬ1е счггепсВв1впсвт снггепСВв1впсе = Ьв1впсе ?? 0.07 Теперь переменная спггепСВа1апсе содержит значение 123.75 переменной Ьа1апсе.
И еще одно замечание: выражение в правой части оператора ".. вычисляется только в том случае, если выражение в левой его части не содержит значение. Этот факт демонстрируется в приведенной ниже программе. // Применение оператора ?? нвзпд яувсвв; с1ввв Нн11вЫеввво2 ( // Возвратить нулевой остаток. вгвС1с боиЫв Овгзвговв1() ( Сопво1в.нг1Сеъьпв("В методе Оегзвговв1().")т гесигп 0.07 ) 676 Часть (. Язык С№ ягагъс чокк( Маьп() ( «(опЬ1е? Ьа1апсе = 123.?ем «(опЬ1е спггепсВа1апсе) // Здесь метод ьесхегова1() не вызывается, поскольку // переменная Ьа1апсе содержит конкретное значение. спггепГВа1апсе = Ьа1апсе ?? ПесхегоВа1()) Сопао1е.иг1сеъъпе(снггепсВа1апсе)т В этой программе метод песеегона1() не вызывается, поскольку переменная Ьа1апсе содержит конкретное значение.
Как пояснялось выше, если выражение в левой части оператора ? ? содержит конкретное значение, то выражение в правой его части не вычисляется. Обнуляемые объекты, операторы отношения и логические операторы Обнуляемые объекты могут использоваться в выражениях отношения таким же образом, как и соответствующие объекты необнуляемого типа. Но они должны подчиняться следую)цему дополнительному правилу: когда два обнуляемых объекта сравниваются в операциях <, >, <= или >55 то их результат будет ложным, если любой из обнуляемых объектов оказывается пустым, т.е. содержит значение пп11. В качестве примера рассмотрим следующий фрагмент кода: Ьусе? 1онег = 16т Ьусе? пррег = пп11) // Здесь переменная 1онег определена, а переменная // баррет не определена.
1Г(1онег < пррег) // ложно В данном случае проверка того, что значение одной переменой меньше значения другой, дает ложный результат. Хотя это и не совсем очевидно, как, впрочем, и следующая проверка противоположного характера: 1г(1онег > иррег) // .. также ложно! Следовательно, если один или оба сравниваемых обнуляемых объекта оказываются пустыми, то результат их сравнения всегда будет ложным. Это фактически означает, что пустое значение (пп11) не участвует в отношении порядка.
Тем не менее с помощью операторов == и ! = можно проверить, содержит ли обнуляемый объект пустое значение. Например, следующая проверка вполне допустима и дает истинный результат: 15(баррет == пп11) // Если в логическом выражении участвуют два объекта типа Ьоо1'., то его результат может иметь одно из трех следующих значений: сгпе (истинное), га1зе (ложное) или пп11 (неопределенное). Ниже приведены результаты применения логических операторов а и ( к объектам типа ьоо1'.. Глава 20. Небезопасный код, указатели, обнулиемые тины и разные ключевые слова 677 Р)0 пп11 по 11 Сгпе стае Га1ве Га1ве пп11 пп11 пп11 пп11 сгпе сгпе Га1ве Га1ве пп11 пп11 пп11 пп11 пп11 пп11 И наконец, если логический оператор ! применяется к значению типа Ьоо1?, которое является пустым (пп11), то результат этой операции будет неопределенным (пп11). Частичные типы В версии 2.0 в С() появилась возможность разделять определение класса, структуры или интерфейса иа две или более части с сохранением каждой из иих в отдельном файле.
Это делается с помощью ключевого слова рагсха1. Все эти части объединяются вместе во время компиляции программы. Если модификатор рагсха1 используется для создания частичного типа, то ои принимает следующую общую форму: рвгггв1 тип имя типа ( // где имя типа обозначает имя класса, структуры или интерфейса, разделяемого иа части. Каждая часть получающегося частичного типа должна указываться с модификатором раггба1. рассмотрим пример разделения простого класса, содержащего координаты Х к', иа три отдельных файла. Ниже приведено содержимое первого файла. рагкзв1 с1авв Ху ( рпЫгс ХУ (гпк а, зпк Ь) Х = вт Х=Ы ) ) Далее следует содержимое второго файла.
рагггв1 с1ввв ХУ ( рпЫгс гпг Х ( деки веге ) И наконец, содержимое третьего файла. рвгкга1 с1авв ХУ ( рпЫгс 1пк Х ( сег; вег) ) ) В приведенном ниже файле исходного текста программы демонстрируется применение класса ху. // Продемонстрировать определения частичного класса. ив1по Яувгеи) о78 Часть ), Язык С№ с1азз тезк ( зсакьс ноко Маьп() ( хт ху = пен Ху(1, 2)т Сопзо1е.кгьсеъьпе(ху.Х т "," + ху.т]) ) Для того чтобы воспользоваться классом ху, необходимо включить в компиляцию все его файлы.
Так, если файлы класса Ху называются ху1. сз, ху2. сз и хуЗ. сз, а класс тазг содержится в файле сезс. сз, то для его компиляции достаточно ввести в командиой строке следующее: сес севе.св ху1.св хуз.св хуз.св И последнее замечание: в С№ допускаются частичные обобщенные классы. Но параметры типа в объявлеиии каждого такого класса должны совпадать с теми, что указываются в остальных его частях.
Частичные методы Как пояснялось в предыдущем разделе, с помощью модификатора рагсуа1 можно создать класс частичного типа. В версии С№ 3.0 появилась возможность использовать этот модификатор и для создания частичного метода в элементе данных частичного типа. Частичиый метод объявляется в одной его части, а реализуется в другой. Следовательно, с помощью модификатора рагг№а1 можно отделить объявление метода от его реализации в частичном классе или структуре. Главная особенность частичного метода заключается в том, что его реализация ие требуется! Если частичный метод ие реализуется в другой части класса или структуры, то все его вызовы молча игнорируются.
Это дает возможность определить, ио ие востребовать дополнительные, хотя и ие обязательные функции класса. Если эти функции ие реализованы, то оии просто игнорируются. Ниже приведена расширенная версия предыдущей программы, в которой создается частичиый метод з)том () . Этот метод вызывается другим методом, з)тоыху () . Ради удобства все части класса Ху представлены в одном файле, ио оии могут быть распределены по отдельным файлам, как было показано в предыдущем разделе. // Продемонстрировать применение частичного метода. изьпо Зузсевт рагкьа1 с1взз ХУ ( роп11с ХУ(гпк а, 1пк Ь) ( Х = ат т/ вт ) // Объявить частичный метод. рвгкьа1 нокб звон()т ) Глава 20, Небезопасный код, указатели, обнуллвыыв типы и разные ключевые слова 679 рагс1а1 с1азз Ху ( рчь11с 1пс х ( дею вест ) // Реализовать частичный метод. рагкйа1 чово яном() ( сопзо1е.игткеьвпе("(О), (1)", х, у)т ) ) рагсва1 с1аза ХУ ( рчв11с 1пс У ( цест вест ) // Вызвать частичный метод.
роо11с но1о яноыХу() ( япон () т ) ) с1азз тезс ( всакьс чо1о мавп О ( ХУ ху = пеы Хт(1, 2)т ху.японку()т ) Обратите внимание иа то, что метод я)том () объявляется в одной части класса ху, а реализуется в другой его части. В реализации этого метода выводятся значения координат Х и т'.