Start Debugging
2023-10-28 Обновлено 2023-11-01 csharpdotnet Edit on GitHub

C# параметры ref readonly

Модификатор ref readonly в C# даёт более прозрачный способ передавать ссылки только для чтения. Узнайте, как он улучшает модификатор in за счёт более чётких ограничений и видимости для вызывающей стороны.

Модификатор ref readonly обеспечивает более прозрачный способ передачи ссылок только для чтения в метод. Передача readonly-ссылок была возможна в C# и раньше, через модификатор in, начиная с версии 7.2, но у того синтаксиса были некоторые ограничения, точнее, слишком мало ограничений.

Как же работает новый модификатор? Предположим, у нас следующая сигнатура метода:

void FooRef(ref readonly int bar) { }

Простой вызов метода с передачей целочисленной переменной или значения приведёт к предупреждению компилятора. Обратите внимание: это лишь предупреждение, оно подсвечивает неоднозначность в вашей реализации, но всё равно позволит выполнить код, если вы настаиваете.

var x = 42;

FooRef(x);
FooRef(42);

Разберём их по очереди.

FooRef(x): используем ref или in

Это одно из улучшений по сравнению с использованием модификатора in. ref readonly явно сообщает вызывающей стороне, что значение передаётся по ссылке. С in это не было прозрачно для вызывающего и могло приводить к путанице.

Чтобы исправить CS9192, просто измените вызов так, чтобы явно указать FooRef(ref x) или FooRef(in x). Эти две аннотации в основном эквивалентны; главное отличие в том, что in более снисходителен и допускает передачу не присваиваемых значений, тогда как ref требует присваиваемую переменную.

Например:

readonly int y = 43;

FooRef(in y);
FooRef(ref y);

FooRef(in y) сработает без проблем, тогда как FooRef(ref y) приведёт к ошибке компилятора, говорящей, что ref-значение должно быть присваиваемой переменной.

FooRef(42): разрешены только переменные

Это второе улучшение, которое ref readonly приносит по сравнению с in: он начнёт жаловаться, когда вы попытаетесь передать ему rvalue, то есть значение без места в памяти. Это согласуется с предупреждением выше: если вы попробуете написать FooRef(ref 42), то немедленно получите ошибку компилятора CS1510: A ref or out value must be an assignable variable.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Назад