Я презираю и исправляю параметры для методов. ИМХО, они делают код менее чистым и предоставляют возможности для побочных эффектов. Но я признаю, что я не понимаю их полезности, которая могла бы объяснить часть моего ненависти. Пожалуйста, может кто-нибудь объяснить действительный случай для выхода или ссылки?
Какова действительная причина использования параметра "out" или "ref" в методе?
Ответ 1
В принципе, если вам нужно вернуть более одного значения, это альтернатива использованию чего-то типа Tuple<,>
или настраиваемого типа для инкапсуляции значений. Канонический пример, вероятно, int.TryParse
и связанные с ним методы. Они хотят передать две части информации:
- Проанализированное значение
- Успешно ли синтаксический анализ.
Теперь они могли быть написаны с использованием типа возврата int?
и т.д. в этом случае, но это тот же принцип для других случаев. (Например, Dictionary<,>.TryGetValue
, где значение, хранящееся в словаре, может иметь законное значение.)
Я бы не сказал, что презираю параметры out
и ref
, но я считаю, что они должны использоваться только иногда, и только тогда, когда нет лучшей альтернативы. Большинство использований ref
, которые я вижу в переполнении стека, связаны с непониманием передачи параметров.
Ответ 2
out
предоставляет способ возврата более одного значения. ref
то же самое, за исключением того, что вы также можете передать значение.
Обратите внимание, что вы можете мутировать объект, даже если объявлен без ref
(при условии, что он изменен в первую очередь, конечно).
Альтернативой, которую я предпочитаю out
, является создание класса, содержащего все возвращаемые значения и возвращающего один экземпляр этого класса.
Ответ 3
В "новом" (С# 4.0) lock
используется ref
(технически оператор lock
является синтаксическим сахаром для нового Monitor.Enter перегрузка). Без него было бы невозможно: -)
bool acquiredLock = false;
try
{
Monitor.Enter(lockObject, ref acquiredLock);
// Code that accesses resources that are protected by the lock.
}
finally
{
if (acquiredLock)
{
Monitor.Exit(lockObject);
}
}
поэтому в очень критичных местах есть место для ref
.
Причина, по которой просто возврат значения bool будет недостаточной, заключается в том, что между return true
Monitor.Enter
и bool acquiredLock =
может возникнуть исключение, оставляя вашу программу с вопросом "была ли блокировка лишена?". С параметром ref
эта проблема решена.
Ответ 4
Они почти одинаковы - единственное отличие состоит в том, что переменную, которую вы передаете как параметр out
, не нужно инициализировать, а метод с использованием параметра out
должен установить его на что-то.
int x;
Foo(out x);
int y;
Foo(ref y);
Ref
параметры для данных, которые могут быть изменены, out
параметры для данных, которые являются дополнительным выходом для функции (например, int.TryParse
), которые уже используют возвращаемое значение для чего-то.