Типы-значения и ссылочные типы




Идентификаторы

Имена, или идентификаторы, служат для того чтобы обращаться к программным объектам и различать их, то есть идентифицировать. В идентификаторе могут использоваться буквы, цифры и символ подчеркивания. Прописные и строчные буквы различаются, например, hacker, Hacker и hAcKeR — три разных имени.

Первым символом идентификатора может быть буква или знак подчеркивания, но не цифра. Длина идентификатора не ограничена. Пробелы внутри имен не допускаются.

В идентификаторах C# разрешается использовать, помимо латинских букв, буквы национальных алфавитов. Например, правильными являются идентификаторы Фёкла и calc. Более того, можно применять даже так называемые escape-последовательности Unicode, то есть представлять символ с помощью его кода в шестнадцатеричном виде с префиксом \u, например, \u00F2.

Типы данных

Данные, с которыми работает программа, хранятся в оперативной памяти. Естественно, что компилятору необходимо точно знать, сколько места они занимают, как именно закодированы и какие действия с ними можно выполнять. Все это задается при описании данных с помощью типа.

Тип данных однозначно определяет:

  • внутреннее представление данных, а следовательно и множество их возможных значений;
  • допустимые действия над данными (операции и функции).

Например, целые и вещественные числа, даже если они занимают одинаковый объем памяти, имеют совершенно разные диапазоны возможных значений.

Каждое выражение в программе имеет определенный тип. Компилятор использует информацию о типе при проверке допустимости описанных в программе действий.

Память, в которой хранятся данные во время выполнения программы, делится на две области: стек (stack) и динамическая область, или хип (heap), чаще называемый кучей. Стек используется для хранения величин, память под которые выделяет компилятор, а в динамической области память резервируется и освобождается во время выполнения программы с помощью специальных команд. Основным местом для хранения данных в C# является хип.

Классификация типов

Типы можно классифицировать по разным признакам. Если принять за основу строение элемента, все типы можно разделить на простые (не имеют внутренней структуры) и структурированные (состоят из элементов других типов). По своему "создателю" типы можно разделить на встроенные (стандартные) и определяемые программистом. По способу хранения значений типы делятся на значимые, или типы-значения, и ссылочные. Рассмотрим в первую очередь встроенные типы C#.

Встроенные типы

Встроенные типы не требуют предварительного определения. Для каждого типа существует ключевое слово, которое используется при описании переменных, констант и т. д. Встроенные типы C# приведены в таблице 2.4. Они однозначно соответствуют стандартным классам библиотеки.NET, определенным в пространстве имен System. Как видно из таблицы, существуют несколько вариантов представления целых и вещественных величин. Программист выбирает тип каждой величины, используемой в программе, с учетом необходимого ему диапазона и точности представления данных.

Таблица – Встроенные типы C#

Название Ключевое слово Тип.NET Диапазон значений Описание Размер, битов
Логический тип bool Boolean true, false    
Целые типы sbyte SByte От –128 до 127 Со знаком  
byte Byte От 0 до 255 Без знака  
short Int16 От –32768 до 32767 Со знаком  
ushort UInt16 От 0 до 65535 Без знака  
int Int32 От –2 × 109 до 2 × 109 Со знаком  
uint UInt32 От 0 до 4 × 109 Без знака  
long Int64 От –9 × 1018 до 9 × 1018 Со знаком  
ulong UInt64 От 0 до 18 × 1018 Без знака  
Символьный тип char Char От U+0000 до U+ffff Unicode-символ  
Вещественные float Single От 1.5 × 10-45 до 3.4 × 1038 7 цифр  
double Double От 5.0 × 10-324 до 1.7 × 10308 15–16 цифр  
Финансовый тип decimal Decimal От 1.0 × 10-28 до 7.9 × 1028 28–29 цифр  
Строковый тип string String Длина ограничена объемом доступной памяти Строка из Unicode-символов  
Тип object object Object Можно хранить все, что угодно Всеобщий предок  

Типы-значения и ссылочные типы

Чаще всего типы C# разделяют по способу хранения элементов на типы-значения и ссылочные типы (рис. 2.1). Элементы типов-значений, или значимых типов (value types), представляют собой просто последовательность битов в памяти, необходимый объем которой выделяет компилятор. Иными словами, величины значимых типов хранят свои значения непосредственно. Величина ссылочного типа хранит не сами данные, а ссылку на них (адрес, по которому расположены данные). Сами данные хранятся в хипе.

Несмотря на различия в способе хранения, и типы-значения, и ссылочные типы являются потомками общего базового класса object.


Рис. 2.1 Классификация типов данных C# по способу хранения

рис. 2.2 иллюстрирует разницу между величинами значимого и ссылочного типов. Одни и те же действия над ними выполняются по-разному. Рассмотрим в качестве примера проверку на равенство. Величины значимого типа равны, если равны их значения. Величины ссылочного типа равны, если они ссылаются на одни и те же данные (на рисунке b и c равны, но a не равно b даже при одинаковых значениях). Из этого следует, что если изменить значение одной величины ссылочного типа, это может отразиться на другой.


Рис. 2.2 Хранение в памяти величин значимого и ссылочного типов

Упаковка и распаковка

Для того чтобы величины ссылочного и значимого типов могли использоваться совместно, необходимо иметь возможность преобразования из одного типа в другой. Преобразование из типа-значения в ссылочный тип называется упаковкой (boxing), обратное преобразование — распаковкой (unboxing).

Если величина значимого типа используется в том месте, где требуется ссылочный тип, автоматически выполняется создание промежуточной величины ссылочного типа. При необходимости обратного преобразования с величины ссылочного типа "снимается упаковка", и в дальнейших действиях участвует только ее значение.

Литералы (константы)

Литералами, или константами, называют неизменяемые величины. В C# есть логические, целые, вещественные, символьные и строковые константы, а также константа null. Компилятор, выделив константу в качестве лексемы, относит ее к одному из типов данных по ее внешнему виду. Программист может задать тип константы и самостоятельно.

Описание и примеры констант каждого типа приведены в таблице 2.2

Таблица – Константы в C#

Константа Описание Примеры
Логическая true (истина) или false (ложь) truefalse
Целая Десятичная: последовательность десятичных цифр (0, 1, 2, 3, 4, 5, 6, 7, 8, 9), за которой может следовать суффикс (U, u, L, l, UL, Ul, uL, ul, LU, Lu, lU, lu) 8 0 1992268u 0Lu 199226L
  Шестнадцатеричная: символы 0х или 0Х, за которыми следуют шестнадцатеричные цифры (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F), а за цифрами, в свою очередь, может следовать суффикс (U, u, L, l, UL, Ul, uL, ul, LU, Lu, lU, lu) 0xA 0x1B8 0X00FF0xAU 0x1B8LU0X00FFl
Вещественная С фиксированной точкой: [цифры][.][цифры][суффикс] Суффикс — один из символов F, f, D, d, M, m 5.7.001 35.5.7F.001d 35.5F.001f 35m
  С порядком: [цифры][.][цифры]{E|e}[+|–][цифры] [суффикс] Суффикс — один из символов F, f, D, d, M, m 0.2E6.11e+3 5E-100.2E6D.11e–35E10
Символьная Символ, заключенный в апострофы 'A' 'ю' '*''\0' '\n''\xF' '\x74''\uA81B'
Строковая Последовательность символов, заключенная в кавычки "Здесь был Vasia""\tЗначение r = \xF5 \n""Здесь был \u0056\u0061""C:\\temp\\file1.txt"@"C:\temp\file1.txt"
Константа null Ссылка, которая не указывает ни на какой объект Null

Символьная константа представляет собой любой символ в кодировке Unicode. Символьные константы записываются в одной из четырех форм:

  • "обычный" символ, имеющий графическое представление (кроме апострофа и символа перевода строки) — 'A', 'ю', '*';
  • управляющая последовательность — '\0', '\n';
  • символ в виде шестнадцатеричного кода — '\xF', '\x74';
  • символ в виде escape-последовательности Unicode — '\uA81B'.

Управляющей последовательностью, или простой escape-последовательностью, называют определенный символ, предваряемый обратной косой чертой. Управляющая последовательность интерпретируется как одиночный символ и используется для представления:

  • кодов, не имеющих графического изображения (например, \n — переход в начало следующей строки);
  • символов, имеющих специальное значение в строковых и символьных литералах, например, апострофа (').

Допустимые значения последовательностей приведены в таблице 2.3.

Таблица – Управляющие последовательности в С#

Вид Наименование
\a Звуковой сигнал
\b Возврат на шаг
\f Перевод страницы (формата)
\n Перевод строки
\r Возврат каретки
\t Горизонтальная табуляция
\v Вертикальная табуляция
\\ Обратная косая черта
\' Апостроф
\" Кавычка
\0 Нуль-символ

Символ, представленный в виде шестнадцатеричного кода, начинается с префикса \x, за которым следует код символа. Числовое значение должно находиться в диапазоне от 0 до 216 – 1, иначе возникает ошибка компиляции.

Escape-последовательности Unicode служат для представления символа в кодировке Unicode с помощью его кода в шестнадцатеричном виде с префиксом \u или \U, например, \u00F2, \U00010011. Коды в диапазоне от \U10000 до \U10FFFF представляются в виде двух последовательных символов; коды, превышающие \U10FFFF, не поддерживаются.

Управляющие последовательности обоих видов могут использоваться и в строковых константах, называемых иначе строковыми литералами. Например, если требуется вывести несколько строк, можно объединить их в один литерал, отделив одну строку от другой символами \n:

"Никто не доволен своей\nвнешностью, но каждый доволен\nсвоим умом"

Этот литерал при выводе будет выглядеть так:

Никто не доволен своейвнешностью, но каждый доволенсвоим умом

В C# есть и второй вид литералов — дословные (verbatim strings). Эти литералы предваряются символом @, который отключает обработку управляющих последовательностей и позволяет получать строки в том виде, в котором они записаны. Чаще всего дословные литералы применяются при задании полного пути файла. Посмотрите, насколько лучше воспринимается второй вариант записи одного и того же пути:

"C:\\app\\bin\\debug\\a.exe"@"C:\app\bin\debug\a.exe"

Строка может быть пустой (записывается парой смежных двойных кавычек ""). Пустая символьная константа недопустима.

Константа null представляет собой значение, задаваемое по умолчанию для величин так называемых ссылочных типов, которые мы рассмотрим далее в этой лекции.

Переменные

Переменная — это именованная область памяти, предназначенная для хранения данных определенного типа. Во время выполнения программы значение переменной можно изменять. Все переменные, используемые в программе, должны быть описаны явным образом. При описании для каждой переменной задаются ее имя и тип.

Пример описания целой переменной с именем a и вещественной переменной x:

int a; float x;

Имя переменной служит для обращения к области памяти, в которой хранится значение переменной. Имя дает программист. Тип переменной выбирается, исходя из диапазона и требуемой точности представления данных. При объявлении можно присвоить переменной некоторое начальное значение, то есть инициализировать ее, например:

int a, b = 1; float x = 0.1, y = 0.1f;

Здесь описаны:

  • переменная a типа int, начальное значение которой не присваивается;
  • переменная b типа int, ее начальное значение равно 1;
  • переменные х и y типа float, которым присвоены одинаковые начальные значения 0.1. Разница между ними состоит в том, что для инициализации переменной х сначала формируется константа типа double, а затем она преобразуется к типу float; переменной y значение 0.1 присваивается без промежуточного преобразования.

Рекомендуется всегда инициализировать переменные при описании. При инициализации можно использовать не только константу, но и выражение — главное, чтобы на момент описания оно было вычисляемым, например:

int b = 1, a = 100; int x = b * a + 25;

 

Так называемая область действия переменной, то есть область программы, где можно использовать переменную, начинается в точке ее описания и длится до конца блока, внутри которого она описана. Блок — это код, заключенный в фигурные скобки. Основное назначение блока — группировка операторов. В C# любая переменная описана внутри какого-либо блока: класса, метода или блока внутри метода. Имя переменной должно быть уникальным в области ее действия. Область действия распространяется на вложенные в метод блоки.

 

Именованные константы

Можно запретить изменять значение переменной, задав при ее описании ключевое слово const, например:

const int b = 1; const float x = 0.1, y = 0.1f; // const распространяется на обе переменные

Такие величины называют именованными константами, или просто константами. Они применяются для того, чтобы вместо значений констант можно было использовать в программе их имена. Это делает программу более понятной и облегчает внесение в нее изменений. Именованные константы должны обязательно инициализироваться при описании, например:

const int b = 1, a = 100; const int x = b * a + 25;

Операции и выражения

Выражение — это правило вычисления значения. В выражении участвуют операнды, объединенные знаками операций. Операндами простейшего выражения могут быть константы, переменные и вызовы функций.

Например, a + 2 — это выражение, в котором + является знаком операции, а a и 2 — операндами. Пробелы внутри знака операции, состоящей из нескольких символов, не допускаются. Операции C# приведены в таблице.

Таблица – Операции C#

Категория Знак операции Название
Первичные x() Вызов метода или делегата
x[] Доступ к элементу
x++ Постфиксный инкремент
x-- Постфиксный декремент
new Выделение памяти
typeof Получение типа
checked Проверяемый код
unchecked Непроверяемый код
Унарные + Унарный плюс
- Унарный минус (арифметическое отрицание)
! Логическое отрицание
˜ Поразрядное отрицание
++x Префиксный инкремент
--x Префиксный декремент
(тип)x Преобразование типа
Мультипликативные (типа умножения) * Умножение
/ Деление
% Остаток от деления
Аддитивные (типа сложения) + Сложение
- Вычитание
Сдвига << Сдвиг влево
>> Сдвиг вправо
Отношения и проверки типа < Меньше
> Больше
<= Меньше или равно
>= Больше или равно
is Проверка принадлежности типу
as Приведение типа
Проверки на равенство == Равно
!= Не равно
Поразрядные логические & Поразрядная конъюнкция (И)
Поразрядное исключающее ИЛИ
| Поразрядная дизъюнкция (ИЛИ)
Условные логические && Логическое И
|| Логическое ИЛИ
Условная ?: Условная операция
Присваивания = Присваивание
*= Умножение с присваиванием
/= Деление с присваиванием
%= Остаток отделения с присваиванием
+= Сложение с присваиванием
-= Вычитание с присваиванием
<<= Сдвиг влево с присваиванием
>>= Сдвиг вправо с присваиванием
&= Поразрядное И с присваиванием
= Поразрядное исключающее ИЛИ с присваиванием
|= Поразрядное ИЛИ с присваиванием

Операции в выражении выполняются в определенном порядке в соответствии с приоритетами, как и в математике. В таблице операции расположены по убыванию приоритетов, уровни приоритетов разделены в таблице горизонтальными линиями.

Результат вычисления выражения характеризуется значением и типом. Например, пусть a и b — переменные целого типа и описаны так:

int a = 2, b = 5;

Тогда выражение a + b имеет значение 7 и тип int, а выражение a = b имеет значение, равное помещенному в переменную a (в данному случае — 5) и тип, совпадающий с типом этой переменной.

Если в одном выражении соседствует несколько операций одинакового приоритета, операции присваивания и условная операция выполняются справа налево, остальные — слева направо. Для изменения порядка выполнения операций используются круглые скобки, уровень их вложенности практически не ограничен.

Например, a + b + c означает (a + b) + c, а a = b = c означает a = (b = c).

Основные операции C#

В этом разделе кратко описаны синтаксис и применение всех операций C#, кроме некоторых первичных, которые рассматриваются позже при изучении соответствующего материала.

Инкремент и декремент

Операции инкремента (++) и декремента (--) увеличивают и уменьшают операнд на единицу. Они имеют две формы записи — префиксную, когда знак операции записывается перед операндом, и постфиксную. В префиксной форме сначала изменяется операнд, а затем его значение становится результирующим значением выражения, а в постфиксной форме значением выражения является исходное значение операнда, после чего он изменяется.

Стандартные операции инкремента существуют для целых, символьных, вещественных и финансовых величин.

Операция new

Операция new служит для создания нового объекта. Формат операции:

new тип ([ аргументы ])

С помощью этой операции можно создавать объекты как ссылочных, так и значимых типов, например:

object z = new object();int i = new int(); // то же самое, что int i = 0;

При выполнении операции new сначала выделяется необходимый объем памяти (для ссылочных типов в хипе, для значимых — в стеке), а затем вызывается так называемый конструктор по умолчанию, то есть метод, с помощью которого инициализируется объект. Переменной значимого типа присваивается значение по умолчанию, которое равно нулю соответствующего типа.

Операции отрицания

Арифметическое отрицание (унарный минус –) меняет знак операнда на противоположный. Стандартная операция отрицания определена для типов int, long, float, double и decimal. К величинам других типов ее можно применять, если для них возможно неявное преобразование к этим типам.

Логическое отрицание (!) определено для типа bool. Результат операции — значение false, если операнд равен true, и значение true, если операнд равен false.

Поразрядное отрицание (~), часто называемое побитовым, инвертирует каждый разряд в двоичном представлении операнда типа int, uint, long или ulong.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-03-02 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: