Типы данных в языке C#

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

В компьютере эти данные хранятся в определенном виде – в двоичных кодах. Так одно число может кодироваться 1, 2, 4, 8 и более байтами, текст рассматривается как набор символов (1 или 2 байта каждый).

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


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

Для обеспечения контроля типов все переменные, выражения и значения должны принадлежать к определенному типу. Такого понятия, как «бестиповая» переменная, в данном языке программирования вообще не существует. Более того, тип значения определяет те операции, которые разрешается выполнять над ним. Операция, разрешенная для одного типа данных, может оказаться недопустимой для другого.

В C# имеются две общие категории встроенных типов данных: типы значений (value type) и ссылочные типы (reference type). Их классификация приведена на рисунке.

ТипыДанных
Понятие «встроенные типы данных» означает, что для определения переменной выбранного типа вам достаточно указать одно из ключевых слов, указанных в прямоугольниках, и через пробел идентификатор переменной, завершив запись «;», например:
double d;
string s;

Первый оператор объявления переменной d обеспечит ее размещение в стеке, зарезервировав для ее значения ровно 8 байт. Второй оператор зарезервирует место в стеке для ссылки на строку s, содержимое которой после ее инициализации разместится в куче.

Пояснение терминов:
Стек (stack) и куча (heap) относятся к различным сегментам оперативной памяти.
Стек — это область оперативной памяти, которая создаётся для каждого потока. Он работает в порядке LIFO (Last In, First Out), то есть последний добавленный в стек кусок памяти будет первым в очереди на вывод из стека.

Каждый раз, когда функция объявляет новую переменную, она добавляется в стек, а когда эта переменная пропадает из области видимости (например, когда функция заканчивается), она автоматически удаляется из стека. Когда стековая переменная освобождается, эта область памяти становится доступной для других стековых переменных.
Из-за такой природы стека управление памятью оказывается весьма логичным и простым для выполнения на ЦП; это приводит к высокой скорости, в особенности потому, что время цикла обновления байта стека очень мало, т.е. этот байт скорее всего привязан к кэшу процессора.
Тем не менее, у такой строгой формы управления есть и недостатки. Размер стека — это фиксированная величина, и превышение лимита выделенной на стеке памяти приведёт к переполнению стека. Размер задаётся при создании потока, и у каждой переменной есть максимальный размер, зависящий от типа данных.
Это позволяет ограничивать размер некоторых переменных (например, целочисленных), и вынуждает заранее объявлять размер более сложных типов данных (например, массивов), поскольку стек не позволит им изменить его. Кроме того, переменные, расположенные на стеке, всегда являются локальными.

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

Куча — это хранилище памяти, также расположенное в ОЗУ, которое допускает динамическое выделение памяти и не работает по принципу стека: это просто склад для ваших переменных.
Когда вы выделяете в куче участок памяти для хранения переменной, к ней можно обратиться не только в потоке, но и во всем приложении. Именно так определяются глобальные переменные. По завершении приложения все выделенные участки памяти освобождаются.
Размер кучи задаётся при запуске приложения, но, в отличие от стека, он ограничен лишь физически, и это позволяет создавать динамические переменные.

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

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

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

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

В .NET Framework, например, к типу значений с плавающей точкой относится тип double (ключевое слово, псевдоним типа). Любое число этого типа занимает ровно 8 байт оперативной памяти. А число типа decimal занимает уже 16 байт (128 бит). Ключевое слово char используется для представления символа Юникода. Значение символа char представляет собой 16-разрядное числовое (порядковое) значение.

Подсказка (про подсказку)
Используйте интеллектуальную подсказку IntelliSense в среде программирования вместо частого поиска в Интернете.
Наберите в тексте программы ключевое слово ushort и просто наведите мышкой на набранное слово. В окне подсказки вы можете прочитать:
struct System.Uint16 Представляет 16-битовое целое без знака.
Слово System, как вы уже знаете, указывает нам на использование одной из библиотек .NET Framework. Без нее, похоже, не обойдется ни одна ваша программа. Через точку указывается встроенный тип данных, являющейся структурой (struct). Наберите ключевое слово string и наведите мышкой. Подсказка:
class System.String Представляет текст как последовательность знаков Юникода
Таким образом, тип String объявляется в классе (class) System.String.
Проделав подобные действия с остальными предопределенными типами данных, получим следующую любопытную таблицу.

Ключевое слово Тип данных Что это? Размер в байтах
bool System.Boolean структура 1
byte System.Byte структура 1
char System.Char структура 2
decimal System.Decimal структура 16
double System.Double структура 8
float System.Single структура 4
int System.Int32 структура 4
long System.Int64 структура 8
object System.Object класс
sbyte System.SByte структура 1
short System.Int16 структура 2
string System.String класс
uint System.UInt32 структура 4
ulong System.UInt64 структура 8
ushort System.UInt16 структура 2

Узнать размер памяти, резервируемой для типов значений (например, long), можно получить, выполнив оператор: Console.WriteLine(sizeof(long));

Заметим, что все типы данных, относящихся к типам значений, задаются структурами, два ссылочных типа задаются классами. Как удивительно просто: поймем, что такое структура и класс, и поймем все?

Вспомним первый принцип ООП – инкапсуляцию и понятие класса. Там указывалось, что основной единицей инкапсуляции в C# является класс, который определяет форму объекта. Он описывает данные, а также код, который будет ими оперировать. В C# описание класса служит для построения объектов, которые являются экземплярами класса. То есть, когда мы объявляем объект (переменную) класса String, то мы получаем доступ к 34 методам (функциям) работы со строкой, свойству Length (длина строки), полю Empty и индексатору.

Структуры похожи на классы, только проще.В языке C# примитивные числовые типы int, long, float являются, как мы выяснили, псевдонимами для структур System.Int32, System.Int64 и System.Single соответственно. Эти структуры имеют поля и методы. Например, каждая из перечисленных структур имеет методы Equals(), GetType(), ToString(). Также у перечисленных структур есть некоторые свойства — статичные поля, например, Int32.MaxValue или Int32.MinValue.

Получается, что используя структуры, вы знакомы с ними. Повторим, что хотя структуры похожи на классы, все же существует принципиальное отличие, которое заключается в том, что класс всегда является ссылочным типом (reference type), а структуры – типом значений (value type).

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

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

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


NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.


Помощь проекту:

Понравилась статья? Поделиться с друзьями:
5 1 голос
Рейтинг статьи
Подписаться
Уведомить о
4 комментариев
Новые
Старые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

Большое спасибо за ваш труд!

Здравствуйте великий человек, который нам помогает познать язык общения с дьявольской машиной. Ваша цитата — Такого понятия, как «бестиповая» переменная, в данном языке программирования вообще не существует., А как-же var? var — и есть неявно типизированные локальные переменные является строго типизированными, как если бы вы объявили тип самостоятельно, однако его определяет компилятор. Если я где-то неправ поправьте меня пожалуйста, я совсем начинающий программист. Мне очень нравится Ваш курс, написано очень доступно, понятно, разжевано! СПАСИБО!!!!!!

Важно: Вы можете поддержать проект и автора.

Класс!

4
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
()
x