← Назад к вопросам

String это значимый или ссылочный тип\?

1.3 Junior🔥 271 комментариев
#Основы C# и .NET

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

String в C#: ссылочный тип

String (строка) в C# является ссылочным типом (reference type), несмотря на некоторые особенности поведения, которые могут напоминать значимые типы (value types).

Почему string — ссылочный тип?

1. Наследование и реализация

public sealed class String : ICloneable, IComparable, IComparable<string>, 
                              IConvertible, IEquatable<string>, IEnumerable<char>

Как видно из определения, string — это sealed-класс, наследующийся от System.Object. Все классы в C# являются ссылочными типами.

2. Расположение в памяти

  • Экземпляры string размещаются в куче (heap)
  • Переменные типа string хранят ссылку на область памяти в куче, а не сами данные
  • Значения по умолчанию: null для ссылочных типов vs. "" (пустая строка через String.Empty)

3. Поведение при присваивании

string str1 = "Hello";
string str2 = str1; // Копируется ссылка, а не содержимое
str2 = "World";     // str1 остаётся "Hello", str2 указывает на новый объект

Console.WriteLine(str1); // "Hello"
Console.WriteLine(str2); // "World"

Особенности поведения string

Иммутабельность (неизменяемость)

string text = "Original";
text += " modified"; // Создаётся НОВЫЙ объект в куче

После этой операции:

  • В памяти существуют два объекта: "Original" и "Original modified"
  • Переменная text теперь ссылается на новый объект
  • Старый объект "Original" становится кандидатом на сборку мусора

Интернирование строк (String Interning)

string s1 = "Hello";
string s2 = "Hello";
string s3 = new string('H', 'e', 'l', 'l', 'o');

bool refEquals1 = ReferenceEquals(s1, s2); // true - одна ссылка
bool refEquals2 = ReferenceEquals(s1, s3); // false - разные объекты
bool valueEquals = s1.Equals(s3);          // true - одинаковое содержимое
  • Компилятор помещает идентичные строковые литералы в пул интернирования
  • ReferenceEquals для s1 и s2 вернёт true, так как они ссылаются на один объект

Почему может возникнуть путаница?

Сходства с value types:

  1. Переопределённые операторы сравнения

    string a = "test";
    string b = "test";
    bool result = (a == b); // true (сравнение по значению, не по ссылке)
    
  2. Неизменяемость создаёт иллюзию копирования значения

  3. Семантика равенства по значению, а не по ссылке

Отличия от value types:

// Value type пример
int x = 10;
int y = x; // Копирование значения
y = 20;    // x остаётся 10

// Reference type пример
StringBuilder sb1 = new StringBuilder("Hello");
StringBuilder sb2 = sb1; // Копирование ссылки
sb2.Append(" World");    // Изменяется общий объект
Console.WriteLine(sb1);  // "Hello World" - ОБА изменились!

Практические следствия

1. Передача в методы

void ModifyString(string input)
{
    input = "Modified"; // Создаётся локальная копия ссылки
}

string original = "Original";
ModifyString(original);
Console.WriteLine(original); // "Original" - не изменился

2. Производительность

Из-за иммутабельности частые модификации строк создают много временных объектов. Решение:

// Плохо для множественных конкатенаций
string result = "";
for (int i = 0; i < 1000; i++)
    result += i.ToString(); // 1000 новых объектов!

// Хорошо - используем StringBuilder
var sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
    sb.Append(i);
string finalResult = sb.ToString(); // Один объект string

Вывод

String — однозначно ссылочный тип, который:

  • Наследуется от System.Object
  • Размещается в управляемой куче
  • Передаётся по ссылке
  • Обладает особенностями (иммутабельность, интернирование, переопределённые операторы сравнения), которые иногда маскируют его ссылочную природу.

Понимание этой двойственности важно для:

  • Оптимизации использования памяти
  • Избежания утечек памяти
  • Корректной работы с многопоточностью
  • Написания эффективного кода при работе с текстовыми данными
String это значимый или ссылочный тип\? | PrepBro