Можно ли передать значимый тип (value type) по ссылке в C#?

«Можно ли передать значимый тип (value type) по ссылке в C#?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, в C# значимые типы (struct, int, bool и т.д.) можно передавать по ссылке, избегая копирования. Для этого используются модификаторы ref, out и in.

1. ref (передача по ссылке с возможностью чтения и записи): Переменная должна быть инициализирована до передачи.

void DoubleValue(ref int number) {
    number *= 2; // Модифицирует оригинальную переменную
}

int value = 5;
DoubleValue(ref value);
Console.WriteLine(value); // Вывод: 10

2. out (передача по ссылке только для записи результата): Метод обязан присвоить значение out-параметру. Переменная может быть неинициализированной.

bool TryDivide(int dividend, int divisor, out int result) {
    if (divisor != 0) {
        result = dividend / divisor; // Обязательное присваивание
        return true;
    }
    result = 0; // Присваивание даже в случае ошибки
    return false;
}

if (TryDivide(10, 2, out int quotient)) {
    Console.WriteLine(quotient); // Вывод: 5
}

3. in (C# 7.2+, передача по ссылке только для чтения): Гарантирует, что метод не изменит передаваемое значение. Полезно для больших структур.

readonly struct LargeStruct { public double X, Y, Z; }

double CalculateDistance(in LargeStruct point) {
    // point.X = 10; // Ошибка компиляции: нельзя модифицировать
    return Math.Sqrt(point.X * point.X + point.Y * point.Y + point.Z * point.Z);
}
Ключевые отличия: Модификатор Инициализация до вызова Обязанность присвоения в методе Возможность чтения в методе Возможность записи в методе
ref Да Нет Да Да
out Нет Да Нет (до присваивания) Да
in Да Нет Да Нет