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)приведёт к предупреждению CS9192: Argument 1 should be passed with ‘ref’ or ‘in’ keywordFooRef(42)приведёт к предупреждению CS9193: Argument 1 should be a variable because it is passed to a ‘ref readonly’ parameter
Разберём их по очереди.
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.