0Pricing
C# Academy · Урок

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

Узнайте, как каждый из них хранится и копируется.

«Типы значений и ссылочные типы» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Типы значений и ссылочные типы
  2. Упаковка и распаковка
  3. Неявные и явные преобразования
  4. Класс Convert и разбор значений
← Назад к C# Academy