Типы значений и ссылочные типы
Узнайте, как каждый из них хранится и копируется.
«Типы значений и ссылочные типы» — бесплатный урок C# Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Два семейства типов
Типы C# делятся на типы-значения (int, double, логические значения, структуры) и ссылочные типы (классы, строки, массивы). Они различаются способом хранения и копирования.
using System;
class Program
{
static void Main()
{
int valueType = 5; // value type
int[] referenceType = { 1, 2, 3 }; // reference type
Console.WriteLine(valueType + ", length " + referenceType.Length);
}
}Типы-значения хранят данные
Переменная типа-значения непосредственно содержит свои данные. Обычно такие данные находятся в стеке или встроены в содержащий их объект.
using System;
class Program
{
static void Main()
{
int a = 10;
double b = 3.14;
bool c = true;
Console.WriteLine(a + ", " + b + ", " + c);
}
}Ссылочные типы хранят адрес
Переменная ссылочного типа хранит ссылку (адрес) на данные, расположенные в куче. Переменная и объект существуют отдельно.
using System;
class Box { public int Value; }
class Program
{
static void Main()
{
Box b = new Box(); // b refers to a heap object
b.Value = 42;
Console.WriteLine(b.Value);
}
}Семантика копирования: типы-значения
Присваивание типа-значения копирует данные. Изменение копии никогда не влияет на исходное значение.
using System;
class Program
{
static void Main()
{
int a = 1;
int b = a; // copy
b = 99;
Console.WriteLine("a=" + a + ", b=" + b);
}
}Семантика копирования: ссылочные типы
При присваивании ссылочного типа копируется ссылка, а не объект. После этого обе переменные указывают на один и тот же объект.
using System;
class Box { public int Value; }
class Program
{
static void Main()
{
Box a = new Box { Value = 1 };
Box b = a; // same object
b.Value = 99;
Console.WriteLine("a.Value=" + a.Value + ", b.Value=" + b.Value);
}
}Структуры являются типами значений
Определяемая Вами struct является типом значения, поэтому при присваивании она копируется так же, как int.
using System;
struct Point { public int X, Y; }
class Program
{
static void Main()
{
Point p1 = new Point { X = 1, Y = 2 };
Point p2 = p1; // full copy
p2.X = 99;
Console.WriteLine("p1.X=" + p1.X + ", p2.X=" + p2.X);
}
}Передача в методы
По умолчанию типы значений передаются путем копирования, а для ссылочных типов копируется ссылка. Поэтому метод может изменить объект класса, видимый вызывающим кодом, но не обычный int.
using System;
class Counter { public int N; }
class Program
{
static void BumpInt(int x) { x++; }
static void BumpObj(Counter c) { c.N++; }
static void Main()
{
int i = 0;
BumpInt(i);
var c = new Counter();
BumpObj(c);
Console.WriteLine("i=" + i + ", c.N=" + c.N);
}
}Пустые значения и ссылочные типы
Только ссылочные типы могут иметь значение null (отсутствие объекта). Типы значений всегда содержат значение, если только они не объявлены допускающими пустое значение с помощью ?.
using System;
class Program
{
static void Main()
{
string text = null; // reference type can be null
int? maybe = null; // nullable value type
Console.WriteLine((text == null) + ", " + (maybe == null));
}
}Различия в сравнении на равенство
Для типов значений оператор == сравнивает данные. Для ссылочных типов оператор == обычно сравнивает идентичность (тот же объект), если только его поведение не переопределено.
using System;
class Program
{
static void Main()
{
int a = 5, b = 5;
Console.WriteLine("ints: " + (a == b)); // True - same value
object o1 = new object();
object o2 = new object();
Console.WriteLine("objects: " + (o1 == o2)); // False - different identity
}
}Значения по умолчанию
Для типов значений по умолчанию используется значение, похожее на нулевое (0, ложное значение), а для ссылочных типов — null.
using System;
class Program
{
static void Main()
{
int defaultInt = default;
bool defaultBool = default;
string defaultString = default;
Console.WriteLine(defaultInt + ", " + defaultBool + ", null? " + (defaultString == null));
}
}Объединяем всё вместе
Зная, является ли тип типом значения или ссылочным типом, Вы можете предсказать поведение при копировании, возможность пустого значения и то, как методы могут его изменять. Это помогает писать корректный код без ошибок.
using System;
struct Money { public decimal Amount; }
class Wallet { public decimal Amount; }
class Program
{
static void Main()
{
Money m1 = new Money { Amount = 10 };
Money m2 = m1; m2.Amount = 99;
Wallet w1 = new Wallet { Amount = 10 };
Wallet w2 = w1; w2.Amount = 99;
Console.WriteLine("Money copy: " + m1.Amount + " (independent)");
Console.WriteLine("Wallet ref: " + w1.Amount + " (shared)");
}
}Быстрая проверка
Проверьте, насколько хорошо Вы понимаете различия между типами значений и ссылочными типами.
Повторение
Типы значений (int, числа двойной точности, логические значения, структуры) хранят данные непосредственно и копируются при присваивании; ссылочные типы (классы, строки, массивы) хранят ссылку на объект в куче и копируют эту ссылку. Только ссылочные типы по умолчанию допускают пустое значение, а поведение при присваивании и сравнение на равенство у этих двух семейств различаются.
using System;
struct V { public int N; }
class R { public int N; }
class Program
{
static void Main()
{
V v1 = new V { N = 1 }; V v2 = v1; v2.N = 9;
R r1 = new R { N = 1 }; R r2 = r1; r2.N = 9;
Console.WriteLine(v1.N + " vs " + r1.N);
}
}Часто задаваемые вопросы
Урок «Типы значений и ссылочные типы» бесплатный?
Да — полный текст урока «Типы значений и ссылочные типы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Типы значений и ссылочные типы»?
Узнайте, как каждый из них хранится и копируется. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Типы значений и ссылочные типы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Типы значений и ссылочные типы
- Упаковка и распаковка
- Неявные и явные преобразования
- Класс Convert и разбор значений