Чем отличаются value от reference type? String - это reference или value?csharp-29

Основные различия между Value и Reference типами

1. Хранение данных

// Value type (хранит значение непосредственно)
int number = 42;  // Значение 42 хранится прямо в переменной

// Reference type (хранит ссылку на объект)
object obj = new object();  // Переменная содержит ссылку на объект в куче

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

  • Value types:
    • Локальные переменные → стек
    • Поля класса → часть объекта в куче
  • Reference types:
    • Всегда в управляемой куче
    • Переменная содержит указатель на объект

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

// Value type - копирование значения
int a = 10;
int b = a;  // Создается независимая копия
b = 20;     // a остается 10

// Reference type - копирование ссылки
var list1 = new List<int> {1, 2, 3};
var list2 = list1;  // Обе переменные ссылаются на один объект
list2.Add(4);       // Изменения видны через list1

4. Значение по умолчанию

  • Value types: 0, false и т.д.
  • Reference types: null

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

  • Value types обычно быстрее для небольших данных
  • Reference types требуют выделения в куче и работы GC

Особый случай: тип String

String - это reference type, но с некоторыми особенностями поведения value type:

  1. Неизменяемость (immutable)

    string s1 = "Hello";
    string s2 = s1;  // Копируется ссылка
    s2 += " world";  // Создается НОВЫЙ объект, s1 не изменяется
    
  2. Сравнение по значению

    string a = "test";
    string b = "test";
    bool equal = (a == b);  // true, хотя обычно у reference types сравниваются ссылки
    
  3. Интернирование строк .NET сохраняет одну копию одинаковых строковых литералов:

    string x = "abc";
    string y = "abc";
    bool sameRef = ReferenceEquals(x, y);  // true в большинстве случаев
    
  4. Хранение в памяти

    • Как reference type, string хранится в куче
    • Но содержимое - массив char, который хранится вместе с объектом

Почему String реализован как reference type?

  1. Гибкость размера: Строки могут быть очень длинными
  2. Экономия памяти: Возможность разделять ссылки на одинаковые строки
  3. Семантика: Строки логически представляют текст, а не числовое значение

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

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

    void ModifyString(string s) { s += " modified"; }
    
    string test = "original";
    ModifyString(test);
    // test останется "original", так как string immutable
    
  2. Использование в структурах:

    public struct Data
    {
        public string Description;  // Reference type внутри value type
        public int Value;
    }
    

Резюмируем:


Основные различия между value и reference типами заключаются в способе хранения и передачи данных. String - особый reference type с value-семантикой, что делает его поведение интуитивно понятным, но важно помнить о его неизменяемой природе. Понимание этих различий критически важно для написания эффективного и корректного кода на C#.