Урок 4. Переменные
В предыдущих примерах мы подсовывали программе готовые данные. Например, в первой программе мы заранее подготовили текст Здравствуй, Мир!, который выводился в текстовом поле. Но, обычно, мы не можем заготовить тексты на все случаи жизни и должны научить программу самой подставлять нужную строчку. Для этой цели используются переменные. Само название говорит за себя - значение, присваемое переменной, может меняться на протяжении выполнения программы.
По сути, к переменным можно относиться как к полочкам в холодильнике. На полочки можно класть какие-то продукты и затем снова доставать их оттуда, или просто заглядывать в них и проверять, есть ли там вообще что-нибудь или кот уже съел сметану.
Впрочем, мы отвлеклись. То же самое и с переменными: в них можно помещать данные и затем при необходимости либо извлекать их оттуда, либо проверять их наличие.
Переменные используются в любом языке программирования. Чтобы использовать переменную в программе, ее необходимо объявить. Хотя все данные на компьютере, в сущности, имеют одинаковый вид (наборы нулей и единиц), переменные бывают разных видов, называемых в их случае типами. Если снова провести аналогию с полочками, то они могут быть разными по высоте, из-за чего некоторые предметы могут умещаться только на определенных полочках. Например, длинные пакеты с молоком на нижней полке, а колбаска на верхней. Это очень важный момент, который нужно запомнить, так как типы играют важную роль в программировании.
Чтобы использовать переменные, их нужно объявлять. Это означает, что им необходимо назначать имя и указать тип. После объявления их можно начинать использовать в качестве единиц хранения для данных. Переменные объявляются с помощью оператора, имеющим следующий синтаксис:
type varName;
Вместо type вы указываете тип переменной, а в varName - название переменной. Тип переменной определяет ее поведение (об этом чуть позже), а имя переменной позволит вам не запутаться среди придуманных вами переменных. Предположим, нам поручили подсчитать число всех попугаев и котов, живущих в Москве:
int parrots; // мы объявили переменную parrots типа int int cats; // мы объявили переменную cats тоже типа int
Используя понятные имена, мы не ошибемся в выборе переменных после подсчета всех попугаев и котов.
При попытке использовать переменную, которая не была объявлена, код не будет компилироваться, о чем вас предупредит компилятор. Поэтому пугаться не нужно, а вернитесь в редактор кода и объявите переменную.
Правила объявления переменных
Следует запомнить несколько несложных правил.
- Переменная должна быть объявлена до ее использования
- Переменную можно объявлять только внутри класса, как часть определения функции или внутри тела функции. (Переменные, объявленные внутри класса, называются полями. Переменные, используемые для определения функции, называются параметрами. Переменные, объявленные внутри функции, называются локальными переменными)
- Переменные должны начинаться с буквы или символа подчеркивания
- Имена переменных могут содержать в себе буквы цифры и значки подчеркивания
- Нельзя использовать в качестве имен переменных ключевые слова
Вот несколько примеров
// Правильные переменные _cat = "кот"; Kitten3 = "Котенку 3 года"; Cat_Name = "Кота зовут Рыжик"; // Неправильные переменные 3Kitten = "кошка"; //начинается с цифры Cat,Me = "Meow"; //нельзя использовать запятую
Можно объявлять более одной переменной в одном операторе присваивания. В этом случае все переменные отделяются запятыми и принадлежат к одному типу
int Cats, Kittens, Dogs;
Кроме того, можно сразу инициализировать объявляемую переменную
int Cats = 7;
Можно также инициализировать переменную динамически, используя любое действительное выражение. Например, мы хотим вычислить периметр квадрата:
int widthSquare = 5; // ширина квадрата // динамически инициализируем переменную perimeter int perimeter = widthSqare * 4;
Еще раз напомню, что язык С# чувствителен регистру (я действительно это говорил?), поэтому будьте аккуратны при создании переменных. Если вы ошибетесь в одной буковке, то программа может работать, но выдавать совсем неправильные результаты. Например, все перечисленные ниже имена переменных будут являться совершенно разными именами:
cat Cat CAT cAt
Присваивания
Компьютеры создавались для вычислений, поэтому в программировании много заимствований из математики. Например, в школе вам приходилось видеть подобные выражения:
A = 3 B = 5 C = 6 D = A + B + C
Если перевести это простое упражнение на язык C#, то выглядеть это будет так:
int A, B, C, D; A = 3; B = 5; C = 6; D = A + B + C;
Иными словами, нам понадобилось просто объявить переменные и проставить точки с запятой в конце каждой строки. Но тем не менее, программирование - это не решение математических задач. Например, в математике допустимо следующее:
A = 3 C = A + B B = 2
В C# менять порядок выражений нельзя. Операторы в C# выполняются последовательно, одно за другим! Во второй строчке примера переменной C присваивается значение суммы переменных A и B, но переменной B мы еще не присвоили никакого значения. Это недопустимо и программа просто не запустится. Также можно использовать круглые скобки для повышения приоритета (аналогично как в математике).
x = y/2 - 3 * z + 127; m = (n/2 - 3* k) - 220;
В C# знак равенства называется оператором присваивания и обозначается знаком =. Оператор - это символ или короткое слово, которые выполняют операцию. У операторов имеются операнды. Например, оператор присваивания имеет два операнда: переменную слева от знака равенства и выражение справа от знака равенства. В данном случае, оператор присваивания заставляет переменную слева от знака равенства быть присвоенной значению, вычисляемому выражением справа.
Кстати, в C# допустимо и такое выражение с оператором присваивания, которое будет неправильным в математике:
C = 2; C = C + 3;
В этом примере во второй строчке переменной C присваивается сумма текущего значения переменной C (т.е. 2) и числа 3.
Теперь рассмотрим еще один пример:
X + 3 = 8;
На самом деле вы не сможете написать такую строчку кода в C#, так программа откажется выполнять эту инструкцию. Слева от оператора разрешен только один тип операнда - переменная. Хотя с точки зрения математики здесь все верно.
С помощью оператора присваивания также можно выстраивать цепочку присваиваний:
int x, y, z; x = y = z = 26; // всем переменным присваивается значение 26
Еще вам придется использовать в своих программах блок кода. Блок кода - это объединение нескольких операторов, заключенное в фигурные скобки. Блок кода позволяет создавать логический элемент, который будет использоваться как одиночный оператор. Обычно блок используется в операторах if и for, который мы будем изучать позже. Пока просто просмотрите на пример:
if(a > t) { v = w * m; l = d - r; }
В этом примере, если переменная a будет больше переменной t, то будут выполняться сразу два оператора умножения и вычитания. По отдельности эти операторы выполняться не будут. Использование блоков кода позволяет создавать специальные алгоритмы для решения различных задач.
Область видимости и время жизни переменных
Итак, блок кода окружается фигурными скобками. Но он также определяет область видимости, которая задает время жизни объявляемых переменных. Объявленная внутри области видимости переменная является недоступной для кода, который расположен за этой областью. Следовательно, при объявлении переменной в пределах ее области видимости, вы локализуете эту переменную и защищаете ее от неразрешенного доступа и модификации. Область видимости может быть вложенной. Каждый раз, создавая новый блок кода, вы создаете новую вложенную область видимости и при этом внешняя область становится видимой для вложенной области. Но при этом объекты, объявленные во внутренней области видимости будут невидимы для кода во внешней области. Рассмотрим пример:
// Пример использования вложенных областей using System; class ScopeDemo { public static void Main() { int x; // это переменная видна всему коду в пределах метода Main x = 10; if(x == 10) { // создается новая область видимости int y = 20; // эта переменная будет видна только в этом блоке // Так как видны обе переменные, мы можем их использовать Console.WriteLine("Сумма переменных x и y равна: " + (x + y)); } // блок кода закончился // y = 100; // если уберете знаки комментария, то получите ошибку! Console.WriteLine("Значение x равно: " + x); } }
Запустите программу. Все будет работать. Теперь попробуйте убрать комментарии у строчки y = 100; и вы получите сообщение об ошибке, так как переменная y была объявлена во внутреннем блоке if и видима только там. Попытка присвоить этой переменной другое значение за пределами этого блока и приводит к ошибке. Тогда как переменная x видна в обоих блоках кода и доступна для использования.
Еще один важный момент связан с временем жизни переменной. Переменные создаются при их объявлении в какой-либо области видимости (при входе в данную область и уничтожаются при выходе из этой области. Это означает, что переменная не будет сохранять свое значение при выходе из своей области видимости, то есть переменная, объявленная в пределах метода, не будет хранить свои значения между вызовами этого метода. Также, переменная, объявленная в рамках блока, будет терять свое значение при выходе из блока. Следовательно, время жизни перменной ограничено ее областью видимости.
Если при объявлении переменной одновременно происходит ее инициализация, то переменная будет повтороно инициализироваться каждый раз при входе в блок, в котором она объявлена. Рассмотрим следующую программу:
// Пример о времени жизни переменной using System; class VarLife { public static void Main() { int x; for(x = 0; x < 3; x++) { int y = -2; // переменная инициализируется каждый раз при входе в блок Console.WriteLine("Значение y равно: " + y); y = 25; Console.WriteLine("Значение y равно: " + y); } } }
Запустив программу, вы увидите следующее:
Значение y равно: -2 Значение y равно: 25 Значение y равно: -2 Значение y равно: 25 Значение y равно: -2 Значение y равно: 25
Как видите, каждый раз при входе в цикл for переменная y принимает значение -2, затем ее присваивается значение 25, которое утрачивается при завершении цикла.
Перед этим мы рассматривали пример с вложенными блоками. Казалось бы, если переменная во внутренней области не видима для кода во внешней области, то можно использовать переменные с одинаковыми именами. Но на самом деле этого делать нельзя (в отличии от C++). Давайте все-таки проверим на собственном опыте:
// Второй пример использования вложенных областей using System; class ScopeDemo2 { public static void Main() { int x; // это переменная видна всему коду в пределах метода Main x = 10; int y = 8; // она тоже видна if(x == 10) { // создается новая область видимости int y = 20; // эта переменная будет видна только в этом блоке // Так как видны обе переменные, мы можем их использовать Console.WriteLine("Сумма переменных x и y равна: " + (x + y)); } // блок кода закончился Console.WriteLine("Значение x равно: " + x); } }
Вы не сможете запустить программу, так как используются две переменные с одинаковыми именами. Проявите фантазию и придумайте одной из переменной другое имя. Неужели вам не хватает других букв?
Соглашения об именовании
Когда вы будете программировать, то вам придется постоянно объявлять переменные. Вы можете давать имена, как вам заблагорассудится. Но у программистов выработались свои стили, которыми они придерживаются во время работы. Особенно это актуально в крупных компаниях, где существуют строгие правила на этот счет. Рассмотрим типичные соглашения об именовании переменных. Раньше наиболее популярной считалась венгерская нотация (Hungarian notation). Эта система подразумевает использование в именах всех переменных стандартных прописных префиксов, указывающих на тип этих переменных. Например, если переменная имеет тип int, тогда в начале ее имени может стоять префикс i, т.е. оно может выглядеть, например, как iCat или iPhone. Применение этой системы позволяет быстро определить тип переменной по первому же взгляду на ее имя. В С# от венгерской нотации уже отходят. Сейчас разработчики стараются именовать переменные в соответствии с их предназначением с использованием двух стилей: PascalCase (стиль языка Pascal) и camelCase ("верблюжий" стиль). В обеих системах на предназначение переменных указывает используемый в их именах регистр. Обе они применяются к именам, которые состоят из нескольких слов, и обе требуют, чтобы все буквы в каждом слове имени были прописными, кроме первой, которая должна быть заглавной. В системе camelCase присутствует еще одно дополнительное правило, требующее, чтобы первое слово начиналось с прописной буквы. Например, как мы можем создать переменную, содержащую имя кота:
CatName // Каждое слово начинается с большой буквы. Это стиль Паскаль catName // У первого слова маленькая буква, у остальных большие. Это верблюжий стиль
Еще встречается способ соединение слова при помощи символа подчеркивания. Но им лучше не пользоваться.
my_cat_name; // не пользуйтесь этим стилем!
Комментарии
При написании кода с использованием переменных очень удобно добавлять пометки, напоминающие о том, что именно делает строчка кода. Например, строка кода предлагает пользователю ввести некоторое число или напомнить программисту, который будет читать ваш код, что этот раздел кода написали вы. Подобные пометки называются комментариями. Комментарии - это текст, который игнорируется компилятором и не влияет на размер получаемого файла. Но наличие подробных комментариев в исходном коде позволяет программисту легче понять программу. Не экономьте на комментариях! Комментарии являются очень важной составляющей программирования. Советую вам сразу использовать комментарии в своих проектах.
Существуют несколько типов комментариев. Наиболее популярны однострочные комментарии. Однострочный комментарий начинается с двойного слэша «//». Все, что справа от них до конца строки, не учитывается при компиляции программы.
int cats = 2; // жили-были два кота
С# поддерживает также многострочные комментарии, заключаемые в комбинации символов «/*» и «*/». В этом случае текст комментария может находиться на многих строчках. Все, что находится между этими разграничительными символами, игнорируется компилятором.
/* Этот текст в коде игнорируется компилятором. Можете вписать сюда хоть целую поэму */
В принципе можно использовать и вложенные комментарии. Но я надеюсь, что вы не будете заниматься такими глупостями.
Существует еще один вид комментариев с тремя (!) подряд слэшами, которые предшествуют классам, методам и т.п. В данных комментариях содержатся теги XML. Компилятор создает специальный XML-файл, который можно потом читать в удобном формате. Более подробно об этом читайте в документации или в статье XML-комментарии в C#.
Реклама