1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 13
Текст из файла (страница 13)
3.1) рассматривается как i n t . Числа, превышающие это значение, трактуются как l o n g . Любые числас плавающей точкой рассматриваются как d o u b l e .В табл. 3.4 показаны константы, объявленные как имеющие конкретные типы, т.е.,в частности, с буквенными дескрипторами в конце. Строчные эти буквы или прописные—значения не имеет, например записи lu и 1U равноценны.Глава 3. Объявление переменных-значений69Окончание табл. 3.'КонстантаТип1.
0double1 . OFfloat1Мdecimaltrueboolfalsebool1а1char•\п'1c h a r (СИМВОЛ НОВОЙ с т р о к и )\xl23"a1string"c h a r ( с и м в о л с ш е с т н а д ц а т е р и ч н ы м ч и с л о в ы м з н а ч е н и е м 123)strings t r i n g ( п у с т а я строка)Человек не рассматривает числа, используемые для счета, как разнотипные. Например, нормальный человек (не программист на С#) не станет задумываться, глядя на число 1, знаковое оно или беззнаковое, "короткое" или "длинное". Хотя для С# все эти типыразличны, даже он понимает, что все они тесно связаны между собой.
Например, в приведенном далее фрагменте исходного текста величина типа i n t преобразуется в l o n g :i n t nValue = 10;long lvalue;l v a l u e = nValue;//Это п р и с в а и в а н и екорректноПеременная типа i n t может быть преобразована в l o n g , поскольку любое значениетипа i n t может храниться в переменной типа l o n g и оба типа представляют собой числа, пригодные для перечислений. С# выполняет такое преобразование автоматически,без каких-либо комментариев.Однако обратное преобразование может вызвать проблемы.
Например, приведенныйдалее фрагмент исходного текста содержит ошибку:long lvalue = 10;i n t nValue;nValue = l v a l u e ;// Неверно!Некоторые значения, которые могут храниться в переменной l o n g , не помещаютсяв переменной типа i n t (ну, например, 4 миллиарда). С# в такой ситуации генерируетсообщение об ошибке, поскольку в процессе преобразования данные могут быть утеряны.
Ошибку такого рода обычно довольно сложно обнаружить.Но что, если вы точно знаете, что такое преобразование вполне допустимо? Например, несмотря на то что переменная l v a l u e имеет тип l o n g , в данной конкретной программе ее значение не может превышать 10 0. В этом случае преобразование переменной l v a l u e типа l o n g в переменную n V a l u e типа i n t совершенно корректно.Вы можете пояснить С#, что отлично понимаете, что делаете, посредством оператораприведения типов:long lvalue = 10;i n t nValue;nValue = ( i n t ) l v a l u e ;70// Все в порядкеЧасть II. Основы программирования в С#Глава 3.
СПри приведении вы размещаете имя требующегося типа в круглых скобках непосредственно перед преобразуемым значением. Приведенная выше запись гласит: "Не волнуйся и преобразуй l v a l u e в тип i n t — я знаю, что делаю, и всю ответственность беру насебя". Конечно, такое утверждение может показаться излишне самоуверенным, но зачастую оно совершенно справедливо.Перечислимые числа могут быть преобразованы в числа с плавающей точкой автоматически, но обратное преобразование требует использования оператора приведения типов, например:double dValue = 1 0 . 0 ;long l v a l u e = ( l o n g ) d V a l u e ;Все приведения к типу d e c i m a l и из него нуждаются в применении оператора приведения типов.
В действительности все числовые типы могут быть преобразованы в другие числовые типы с помощью такого оператора. Однако ни b o o l , ни s t r i n g не могутбыть непосредственно приведены ни к какому иному типу.Встроенные функции С# могут преобразовывать числа, символы или логические переменные в их строковые "эквиваленты". Например, вы можете преобразовать значение t r u e типа b o o l в строку " t r u e " ; однако такое преобразование нельзя рассматривать как непосредственное.
Эти два значения — совершенно разные вещи.Глава 3. Объявление переменных-значений71Глава4Операторы> Выполнение арифметических действийI Логические операции> Составные логические операторыатематики создают переменные и выполняют над ними различные действия, складывая их, умножая, а иногда — представьте себе — даже интегрируя. В главе 3, "Объявление переменных-значений", описано, как объявлять и определять переменные, но там ничего не говорится о том, как их использовать после объявления, чтобы получить что-то полезное. В этой главе рассматриваются операции, которые могут быть произведены над переменными.
Для выполнения операций требуются операторы, такие как +, -, =, < или &. Здесь речь пойдет об арифметических,^логических и других операторах.I Все множество арифметических операторов можно разбить на несколько групп: простые арифметические операторы, операторы присваивания и специальные операторы,присущие только программированию. После такого обзора арифметических операторовнужен обзор логических операторов, но о них будет рассказано несколько позже.Простейшие о п е р а т о р ы•С большинством из этих операторов вы должны были познакомиться еще в школе.Они перечислены в табл. 4.1. Обратите внимание, что в программировании для обозначения умножения используется звездочка (*), а не крестик (х).Большинство этих операторов называются бинарными, поскольку они выполняютсянад двумя значениями: одно из них находится с левой стороны от оператора, а другое —с правой.
Единственным исключением является унарный минус, который столь же прост,как и остальные рассматриваемые здесь операторы:i n t nl = 5;i n t n2 = - n l ;//Теперьзначение п2 равно-5Значение -п представляет собой отрицательное значение п.Оператор деления по модулю может быть вам незнаком. Деление по модулю анало- 1гично получению остатка после деления. Так, 5%3 равно 2 ( 5 / 3 = 1, остаток 2), а^25%3 Iравен 1 ( 2 5 / 3 = 8, остаток 1).Строгое определение оператора % выглядит как х= ( х / у ) *у + ( х % у ) .Арифметические операторы (кроме деления по модулю) определены для всех типовпеременных.
Оператор же деления по модулю не определен для чисел с плавающей точ- Iкой, поскольку при делении значений с плавающей точкой не существует остатка.Порядок выполнения операторовЗначение некоторых выражений может оказаться непонятным. Например, рассмот- |рим выражение:int П = 5 * 3 + 2 ;Что имел в виду написавший такую строку программист? Что надо умножить 5 на 3,а затем прибавить 2? Или сначала сложить 3 и 2, а результат умножить на 5?|С# обычно выполняет операторы слева направо, так что результатом приведен- Iного примера будет значение, равное 17.С# вычисляет значение п в представленном далее выражении, сначала деля 24 на 6,а затем деля получившееся значение на 2 :intп=24/6/2;Однако у операторов есть своя иерархия, приоритеты, или проще — свой порядоквыполнения.
С# считывает все выражение и определяет, какие операторы имеют наивысший приоритет и должны быть выполнены до операторов с меньшим приоритетом. IНапример, приоритет умножения выше, чем сложения. Во многих книгах изложениюэтого вопроса посвящены целые главы, но сейчас не стоит забивать этим ни главу, нивашу голову.Никогда не полагайтесь на то, что вы (или кто-то иной) помните приоритеты Iоператоров. Явно указывайте подразумеваемый порядок выполнения выражения посредством скобок.Значение следующего выражения совершенно очевидно и не зависит от приоритетаоператоров:int п =74(7%3)*(4+( 6 / 3 ) ) ;Часть //.
Основы программирования в С# [Скобки перекрывают приоритеты операторов, явно указывая, как именно компилятордолжен интерпретировать выражение. С# ищет наиболее вложенную пару скобок и вычисляет выражение в ней — в данном случае это 6 / 3 , что дает значение 2. В результатеполучается:int п = (7 % 3)*(4 + 2) ;// 2 = 6 / 3Затем С# продолжает поиск скобок и вычисляет значения в них, что приводит к выражению:int n = 1 * 6 ;/ / 6 = 4 + 2,1 = 7 % 3Так что в конечном счете получается:int П = 6;Правило "всегда используйте скобки" имеет, пожалуй, одно исключение. Лично мнес этим сложно примириться, но многие программисты опускают скобки в выраженияхнаподобие приведенного ниже, поскольку очевидно, что умножение имеет более высокий приоритет, чем сложение:int п = 7 + 2*3;//То ж е ,что и 7 +( 2 * 3 )Оператор п р и с в а и в а н и яС# унаследовал одну интересную концепцию от С и С++: присваивание является бинарным оператором, возвращающим значение аргумента справа от него.
Присваиваниеимеет тот же тип, что и оба аргумента (типы которых должны быть одинаковы).Этот новый взгляд на присваивание никак не влияет на выражения, с которыми выуже сталкивались:П= 5 * 3;В данном примере 5 * 3 = 15 и имеет тип i n t . Оператор присваивания сохраняет этоint-значение справа в i n t - п е р е м е н н о й слева и возвращает значение 1 5 . То, что он возвращает значение, позволяет, например, сохранить это значение еще в одной переменной, т.е. написать:m= п = 5 * 3;При наличии нескольких присваиваний они выполняются справа налево.
В приведенном выше выражении правый оператор присваивания сохраняет значение 15 в переменной п и возвращает 15, после чего левый оператор присваивания сохраняет значение 15в переменной m и возвращает 15 (это возвращенное значение в данном примере большеникак не используется).Такое странное определение присваивания делает корректным такой причудливый фрагмент, как показанный ниже (хотя я и предпочитаю воздерживаться от подобных вещей):int n;int m;П = m = 2 ;Старайтесь избегать цепочек присваиваний, поскольку они менее понятны человеку,читающему исходный текст программы. Всего, что может запутать человека, читающегоисходный текст вашей программы (включая и лично вас), следует избегать.
Любые неясности ведут к ошибкам. Огромная часть программирования — от правил языка и егоконструкций до соглашений по именованию переменных и рекомендаций, основанныхна опыте программистов — нацелены на одно: устранение ошибок в программах.[лава 4. Операторы75С# добавляет ко множеству простейших операторов небольшое подмножество операторов, построенных на основе других бинарных операторов. Например, выражениеП +=1;эквивалентно следующему:П = П +1 ;Такие операторы присваивания существуют почти для всех бинарных операторов. IВ табл. 4.2 показаны наиболее распространенные составные операторы присваивания.Т а б л и ц а 4.2. Составные операторы присваиванияОператорЗначениеВ табл.
4.2 опущено два более сложных составных оператора присваивания, <<= и >>=.Операторы побитового сдвига, на которых они основаны, будут рассмотрены позжев этой главе.Оператор инкрементаСреди всех сложений, выполняемых в программах, добавление 1 к переменной —наиболее распространенная операция:n = n +1;// У в е л и ч е н и е п на1С# позволяет записать такую операцию сокращенно:n +=1;// У в е л и ч е н и е п на1Но, оказывается, и это недостаточно кратко, и в С# имеется еще более краткое обозначение этого действия — оператор инкремента:++п;// Увеличение п на 1Все три приведенных выражения функционально эквивалентны, т.е.