Можно ли не инициализировать все out аргументы внутри метода в C#
Что проверяют
Знаете ли вы правило определённого присваивания и понимаете ли, чем out отличается от ref. Следом обычно просят написать метод в стиле TryParse и спрашивают, что присваивать в out при неудаче.
Как отвечать
Нет, не получится. Компилятор требует, чтобы каждый out-параметр был гарантированно присвоен на всех путях, которые завершают метод обычным возвратом, иначе ошибка CS0177. Используется ли параметр внутри метода, значения не имеет.
Естественное исключение одно: путь, который заканчивается throw, присваивания не требует, потому что вызывающий код значение всё равно не получит.
Остальные правила вокруг out:
- внутри метода: читать параметр до присваивания нельзя, это CS0269. Метод обязан считать, что на входе ничего осмысленного нет;
- у вызывающего: переменную не нужно инициализировать заранее, после вызова она считается присвоенной. С C# 7 её можно объявить прямо в вызове:
int.TryParse(s, out var n), а ненужное значение отбросить черезout _; ref: наоборот, требует инициализации до вызова и не требует присваивания в методе;- ограничения:
out-параметров не бывает уasync-методов и итераторов, а захватить такой параметр в лямбде или локальной функции нельзя.
Для Try-методов принят шаблон: первой строкой value = default;, дальше логика, возвращающая bool. С nullable reference types на параметр вешают [NotNullWhen(true)], чтобы анализатор знал, что при true значение не null.
Если метод возвращает несколько значений, упомяните альтернативу: кортеж (int result, bool ok) или record читаются лучше пачки out-параметров.
Где спотыкаются
Говорят, что неиспользуемый out можно оставить без значения. Код из такого ответа просто не скомпилируется.
Путают стороны правила и думают, что инициализировать должен вызывающий. Это требование ref, а для out ответственность целиком на методе.
Считают, что out-параметр автоматически получает default, как поле класса. Для параметров и локальных переменных такого нет, отсюда и ошибка компиляции, и привычка присваивать default явно в начале метода.