KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Симон Робинсон - C# для профессионалов. Том II

Симон Робинсон - C# для профессионалов. Том II

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Симон Робинсон, "C# для профессионалов. Том II" бесплатно, без регистрации.
Перейти на страницу:

Так как C# создан с целью обеспечить большую безопасность типов, чем C++, он менее гибок в отношении преобразований между типами данных, Он также формализует понятие явного и неявного преобразования типов данных. Некоторые преобразования определены как неявные, что позволяет выполнить их либо с помощью неявного, либо явного синтаксиса. Другие можно делать только с помощью явного преобразования типов, и компилятор будет давать ошибку (а не предупреждение, как в C++), если попробовать выполнить его неявно.

Правила в C#, имеющие отношение к тому, какие базовые числовые типы данных могут быть преобразованы в другие типы данных, вполне логичны. Неявными преобразованиями будут преобразования, которые не создают риск потери данных, например, int в long или float в double. Явными преобразованиями являются такие, где может быть потеря данных в связи с ошибкой переполнения, ошибкой знака или потерей дробной части числа, например, float в int, int в uint или short в ulong. Кроме того, так как char рассматривается несколько отдельно от других целых типов данных, можно преобразовывать только явно в или из char.

Следующие выражения считаются допустимыми в коде C#:

float f1 = 40.0F;

long l1 = (long)f1; // явное, так как возможна ошибка округления

short s1 = (short)l1; // явное, так как возможна ошибка переполнения

int i1 = s1; // неявное — никаких проблем

uint i2 = (uint)i1; // явное, так как возможна ошибка знака

Отметим, что в C# явное преобразование типов данных всегда делается с помощью старого синтаксиса в стиле C. Новый синтаксис C++ использовать нельзя.

uint i2 = uint(i1); // неверный синтаксис - это не будет компилироваться

Проверяемое (checked) преобразование типов данных

C# предлагает возможность выполнять преобразования типов и другие арифметические операции в проверяемом (checked) контексте. Это означает, что среда выполнения .NET будет обнаруживать возникновение переполнения и порождать исключение (конкретно, OverFlowException). Это свойство не имеет аналога в C++.

checked {

 int I1 = -3;

 uint I2 = (uint)I1;

}

В связи с контролируемостью контекста вторая строка будет порождать исключение. Если не определить checked, исключения не возникнет и переменная I2 будет содержать мусор.

Строки 

Обработка строк выполняется значительно легче в C#, чем это было раньше в C++. Это связано с понятием строки как базового типа данных, который распознается компилятором C#. В C# нет необходимости рассматривать строки как массивы символов.

Ближайшим эквивалентом для типа данных string в C# является класс string в C++ в стандартной библиотеке. Однако строка C# отличается от строки C++ следующими основными свойствами.

□ Строка C# содержит символы Unicode, а не ANSI.

□ Строка C# имеет значительно больше методов и свойств, чем версия в C++.

□ Класс string стандартной библиотеки C++ является не более чем классом, предоставленным библиотекой, в то время как в C# синтаксис языка специально поддерживает класс string как часть языка.

Последовательности кодирования

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

Последовательность Имя символа Кодировка Unicode ' Одиночная кавычка 0x0027 " Двойная кавычка 0x0022 \ Обратный слэш 0х005C Null 0x0000 a Сигнал 0x0007 b Возврат на одну позицию 0x0008 f Перевод страницы 0x000C n Новая строка 0x000A r Возврат каретки 0x000D t Горизонтальная табуляция 0x0009 v Вертикальная табуляция 0x000B

Это по сути означает, что в C# используются те же коды, что и в C++, за исключением того, что C# не распознает ?.

Имеются два отличия между символами кодирования в C++ и C#:

□ Последовательность кодирования распознается в C#. Однако она не используется как терминатор строки в C# и поэтому может встраиваться в строку. Строки C# работают, сохраняя отдельно свои длины, поэтому никакой символ не используется в качестве терминатора. Поэтому строки C# в действительности могут содержать любой символ Unicode.

□ C# имеет дополнительную последовательность кодирования uxxxx (или эквивалентно Uxxxx), где xxxx представляет 4-символьное шестнадцатеричное число, uxxxx представляет символ Unicode xxxx, например, u0065 представляет 'е'. Однако в отличие от других последовательностей кодирования uxxxx может использоваться в именах переменных, а также в символьных и строковых константах. Например, следующий код допустим в C#.

int Ru0065sult; // тот же результат, что и int Result;

Result = 10;

Согласно документации последовательность кодирования не зависит от регистра символов: uxxxx и Uxxxx будут эквивалентны. Однако при написании этой книги обнаружилось, что только версия нижнего регистра успешно компилируется текущей версией .NET.

C# имеет также альтернативный метод представления строк, который более удобен для строк, содержащих специальные символы: размещение символа @ в начале строки избавляет все символы от кодирования. Эти строки называются дословными строками. Например, чтобы представить строку C:BookChapter2 можно написать либо "C:\Book\Chaptеr2", либо @"C:BookChapter2". Интересно, что это означает также, что можно включать символы возврата каретки в дословные строки без кодирования:

string Message = @"Это будет на первой строке,

а это будет на следующей строке"

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

C# разделяет все типы данных на две разновидности: типы значений и ссылочные типы. Это различие не имеет эквивалента в C++, где переменные всегда неявно содержат значения, если только переменная специально не объявлена как ссылка на другую переменную.

В C# тип значения действительно содержит свое значение. Все предопределенные типы данных в C# являются типами значений, за исключением object и string. Если определить свои собственные структуры и перечисления, они также будут типами значений. Это означает, что простые типы данных в C# обычно действуют точно таким же образом как в C++, когда им присваивают значения.

int I = 10;

long J = I; // создаёт копию значения 10

I = 15; //не влияет на J

Ссылочный тип, как предполагает его имя, содержит только ссылку на то место в памяти, где хранятся данные. Синтаксически он действует таким же образом как ссылки в C++, но в терминах того, что происходит реально, ссылки C# ближе к указателям C++. В C# object и string являются ссылочными типами, как и любые определенные самостоятельно классы. Ссылки C# могут быть переназначены для указания на другие элементы данных, по большей части таким же образом, как можно переназначить указатели C++. Также ссылкам C# можно присваивать значение null для указания, что они ни на что не ссылаются. Например, возьмем класс с именем MyClass, который имеет открытое свойство Width.

MyClass My1 = new MyClass(); // в C# new просто вызывает конструктор

My1.Width = 20;

MyClass My2 = My1; // My2 указывает теперь на то же место

                   // в памяти, что и My1

Му2.Width = 30; // Теперь My1.Width = 30, так как My1

                // и Му2 указывают на одно место в памяти

My2 = null; // Теперь My2 не ссылается ни на что,

            // My1 по прежнему ссылается на тот же объект

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

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

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*