Чем параметр in отличается от ref и out? Зачем передавать большую struct через in вместо копирования по значению?
Что это: Параметр in передаёт readonly-ссылку на аргумент: метод читает значение без копирования, но не может его изменить. ref позволяет читать и писать, out требует присвоения внутри метода. in удобен для крупных struct, где копирование по значению дорого.
Почему важно: Это базовая тема передачи параметров: понимание in показывает, что C# оптимизирует struct не только через стек, но и через readonly-ссылки без boxing.
Под капотом: Компилятор генерирует managed pointer с атрибутом IsReadOnly в IL. JIT передаёт адрес struct, а попытка записи блокируется на этапе компиляции (CS8331). Для мелких struct компилятор может всё равно передать по значению как оптимизацию.
Типичная ошибка: Разработчики помечают маленькие struct параметром in «для скорости» и усложняют сигнатуру, хотя для int или Point копирование дешевле, а readonly ref иногда мешает оптимизациям регистров.
struct Matrix4x4 { public float M11; /* ... 15 полей */ }
void Transform(in Matrix4x4 matrix)
{
// matrix = default; // CS8331: нельзя присвоить in-параметру
Use(matrix.M11);
}
Matrix4x4 m = default;
Transform(in m); // передаётся ссылка, без копирования 64 байт