Чтение онлайн

на главную - закладки

Жанры

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

Ватсон Карли

Шрифт:

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

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

bool
будут содержать
false
, а все ссылочные типы (включая строки и объекты) будут содержать ссылку
null
. Структуры инициализируют нулем каждый свой член.

□ Локальные переменные методов не инициализируются по умолчанию. Однако компилятор будет давать ошибку, если локальная переменная используется до инициализации. Можно при желании инициализировать переменную, вызывая ее конструктор по умолчанию (тот, который обнуляет память).

// локальные переменные метода

int X1; //в этом месте X1 содержит случайные данные

// int Y = X1; // эта закомментированная строка будет создавать ошибку

// компиляции, т.к. X1 используется до инициализации

X1 = new int; // теперь X1 будет содержать ноль.

Упаковка

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

int J = 10;

object BoxedJ = (object)J;

Упаковка действует как любое другое преобразование типов, но надо знать, что содержимое переменной скопируется в кучу и будет создана ссылка (так как объект

BoxedJ
является ссылочным типом).

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

int J = 10;

object BoxedJ = (object)J;

int K = (int)BoxedJ;

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

Управление памятью

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

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

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

int j = 30;

CMyClass *pMine = new CMyClass;

Здесь содержимое

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

int J = 30;

MyClass Mine = new MyClass;

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

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

int* рj = new int(30);

CMyClass Mine;

Это приведет к тому, что

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

Другое различие состоит в том, что в C# не существует эквивалента оператора C++

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

В C# следующие типы данных всегда являются типами значений:

□ Все простые предопределенные типы (за исключением

object
и
string
)

□ Все структуры

□ Все перечисления

Следующие типы данных всегда являются ссылочными типами:

object

string

□ Все классы

Оператор new

Оператор

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

MyClass Mine; // Просто объявляем ссылку. Аналогично объявлению

// неинициализированного указателя в C++

Mine = new MyClass; // создает экземпляр MyClass. Вызывает

// конструктор без параметров, в процессе этого

// выделяет память в куче

MyStruct Struct; // создает экземпляр MyStruct, но не вызывает

// никакого конструкторе. Поля в MyStruct

Поделиться:
Популярные книги

Отверженный. Дилогия

Опсокополос Алексис
Отверженный
Фантастика:
фэнтези
7.51
рейтинг книги
Отверженный. Дилогия

Кодекс Крови. Книга V

Борзых М.
5. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга V

Идеальный мир для Лекаря 28

Сапфир Олег
28. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 28

Убивать чтобы жить 3

Бор Жорж
3. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 3

Бракованная невеста. Академия драконов

Милославская Анастасия
Фантастика:
фэнтези
сказочная фантастика
5.00
рейтинг книги
Бракованная невеста. Академия драконов

Кодекс Охотника. Книга XIX

Винокуров Юрий
19. Кодекс Охотника
Фантастика:
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XIX

На распутье

Кронос Александр
2. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На распутье

Контракт на материнство

Вильде Арина
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Контракт на материнство

Волков. Гимназия №6

Пылаев Валерий
1. Волков
Фантастика:
попаданцы
альтернативная история
аниме
7.00
рейтинг книги
Волков. Гимназия №6

Элита элит

Злотников Роман Валерьевич
1. Элита элит
Фантастика:
боевая фантастика
8.93
рейтинг книги
Элита элит

Седьмая жена короля

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Седьмая жена короля

Измена. Наследник для дракона

Солт Елена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Измена. Наследник для дракона

Темный Лекарь 5

Токсик Саша
5. Темный Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Темный Лекарь 5

Гримуар темного лорда IX

Грехов Тимофей
9. Гримуар темного лорда
Фантастика:
попаданцы
альтернативная история
аниме
фэнтези
5.00
рейтинг книги
Гримуар темного лорда IX