Понятия класса и объекта. Ссылочные типы и значимые типы

Урок посвящен понятиям класса и объекта в C#, а также ссылочным и значимым типам данных

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

Класс можно для себя представить как чертеж, некоторое абстрактное представление сущности. С помощью классов мы моделируем различные понятия или группы понятий из реального мира, например, Автомобиль, Собака, Стол, Сервер, Сокет, Студент и т. п.

Класс – это некоторое описание того, какую информацию должен содержать его экземпляр. Точно так же как чертеж используется для создания какого-либо механизма, устройства или конструкции, класс используется для создания объектов.

Для объявления класса в C# используется ключевое слово class, перед ним указываются модификаторы доступа и ряд других ключевых слов, которые определяют его свойства (статический, абстрактный и т. п.).

Например, создадим простой класс Person.

class Person
{
    public string Name {get; set;}
    public int Age {get; set;}
}

У этого класса два свойства: Имя – Name и Возраст – Age, значения которых можно считывать и изменять.

Пока от вас не требуется понимания смысла всех ключевых слов типа publicgetset и т. п. Постарайтесь понять его на уровне концепции.

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

var p1 = new Person() 
{ 
    Name = "John", 
    Age = 21 
};

var p2 = new Person() 
{ 
    Name = "Mary", 
    Age = 25
};

В примере, p1 и p2 – это объекты класса Person.

Выведем на консоль содержимое их полей:

// p1: Name: John, Age: 21
Console.WriteLine($"p1: Name: {p1.Name}, Age: {p1.Age}"); 

// p2: Name: John, Age: 25
Console.WriteLine($"p2: Name: {p1.Name}, Age: {p1.Age}");

То, о чем мы с вами будет говорить на этом шаге, может показаться на первый взгляд сложным. Если сразу не стало всё понятно, вернитесь к этой информации чуть позже.

Типы данных в C# можно разделить на типы-значения (value type) и ссылочные типы (reference type). В первую очередь они отличаются схемой наследования, местом размещения и представлением.

Для начала стоит сказать о том, что такое стек и управляемая кучаСтек – это область памяти процесса, особенность которой состоит в том, что участки из нее выделяются по принципу LIFO (last in – first out, последним пришёл – первым вышел) – первым доступным элементом является тот, что был помещен последним. Аналогией является стопка тарелок, в которой, для того чтобы добраться до какой-то из них, вам нужно снять сверху все те, что мешают достать нужную.

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

Пусть у нас есть три элемента данных, которые хранятся в стеке:

Если мы хотим добавить в него ещё два элемента 4 и 5, то это мы сможет сделать, только разместив их сверху, по очереди:

Куча – это также область памяти процесса, но в отличие от стека, в ней нет жесткой структуры хранения. За уничтожение объектов, которые в ней размещены, в .NET отвечает сборщик мусора (garbage collector). В таких языках, как C / C++ за этим должен следить сам разработчик.

Все типы в C#, как мы говорили выше, являются наследниками от System.Object. Все типы-значения, помимо этого, являются наследниками ValueType.

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

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

Для часто используемых типов предусмотрена отдельная подгруппа, которую называют типы-значения (value type). Их особенностью является то, что экземпляры этих типов располагаются в стеке, что позволяет их быстро создавать и уничтожать. Фактически время жизни такой переменной определяется контекстом, в котором она объявлена. Из-за этой особенности снижается нагрузка на кучу и сборщик мусора. Последний просто не вызывается для экземпляров типов-значений.

Следует заметить, что если экземпляр типа-значения (например, int) является составляющей частью какого-то ссылочного типа, то он будет располагаться в куче.

Типы-значения являются классами наследниками от System.ValueType, который, в свою очередь, наследуется от System.ObjectОт типов-значений нельзя наследоваться.

Более подробно про эти типы мы поговорим в двух ближайших уроках этого модуля.

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

Если Вы хотите больше узнать про язык C#, приглашаем Вас на наш курс “C#. Базовый уровень“.

Добавить комментарий

Ваш адрес email не будет опубликован.