В каких ситуациях полезны параметры "out" (где "ref" не может использоваться вместо этого)?
Насколько я могу судить, единственным параметром для out
является то, что вызывающий может получить несколько возвращаемых значений из одного вызова метода. Но мы можем также получить несколько значений результата, используя ref
параметры!
Итак, существуют ли другие ситуации, когда параметры out
могут оказаться полезными и где мы не могли бы использовать параметры ref
вместо этого?
Спасибо.
Ответы
Ответ 1
Да - разница между ref
и out
выражается в терминах определенного назначения:
-
Параметр out
не обязательно должен быть определен назначателем перед вызовом метода. Он должен быть определенно назначен в методе до того, как он вернется нормально (т.е. Без исключения). Затем переменная определенно назначается в вызывающем абоненте после вызова.
-
Параметр A ref
должен быть определенно назначен вызывающим абонентом перед вызовом метода. В этом методе необязательно назначать другое значение.
Итак, предположим, что мы хотели изменить int.TryParse(string, out int)
вместо ref
. Обычно код вызова выглядит следующим образом:
int value;
if (int.TryParse(text, out value))
{
// Use value
}
else
{
// Do something else
}
Теперь, если мы использовали ref
, нам нужно было бы дать value
значение перед вызовом, например:
int value = 0;
if (int.TryParse(text, ref value))
{
// Use value
}
else
{
// Do something else
}
Очевидно, это не огромная разница, но это дает неправильное впечатление. Мы назначаем ценность, которую мы не собираемся использовать, и это не очень хорошо для читаемости. Параметр out
указывает, что из метода будет выведено значение (при условии отсутствия исключения) и что вам не нужно начинать с значения.
Однажды из предложений, которые я сделал для С# 5 (я понятия не имею, будет ли это занят или нет) заключается в том, что метод с параметром out
должен иметь возможность рассматривать как метод, возвращающий кортеж значений. В сочетании с лучшей поддержкой кортежей это означало бы, что мы могли бы сделать что-то вроде этого:
var (ok, value) = int.TryParse(text);
В этом случае ok
и value
будут неявно напечатаны на bool
и int
соответственно. Таким образом, выясняется, что входит в метод (text
) и то, что выходит (две части информации: ok
и value
).
Это было бы просто не доступно, если вместо int.TryParse
был использован параметр ref
- поскольку компилятор не может знать, будет ли он действительно заботиться об исходном значении параметра ref
.
Ответ 2
Вы можете посмотреть параметры таким образом:
-
нормальные параметры находятся в параметрах:
Значение может входить в функцию через такой параметр; поэтому он должен быть инициализирован.
Параметры -
ref
являются параметрами входа:
Значение может входить и выходить из функции через такой параметр. Из-за первого, он также должен быть инициализирован.
Параметры -
out
отсутствуют:
Значение должно возвращаться только из функции через такой параметр; поэтому его не нужно инициализировать.
Я придумал этот способ взглянуть на параметры ref
/out
, изучив технологию Microsoft COM. IDL (язык описания интерфейса) используется для описания интерфейсов COM-компонента, а с IDL параметры дополняются деклараторами in
, out
и inout
. Я подозреваю, что .NET и С# частично унаследовали эти объявления от COM, хотя и с немного другими именами (ref
вместо inout
).
С COM параметры out
часто используются для получения фактического возвращаемого значения метода интерфейса, так как "реальное" возвращаемое значение часто используется для возврата кода успеха/ошибки HRESULT
.
С .NET я считаю, что параметры out
имеют гораздо меньшее значение, даже в тех случаях, когда вы хотите вернуть несколько значений из метода (вы можете вернуть сложные объекты или Tuple
в этих ситуациях).
Ответ 3
Важным отличием является следующее:
Переменная, переданная как аргумент out не нужно инициализировать. Однако out должен быть присвоен значение перед возвратом метода.
(параметр ref не требует этого)
Источник: http://msdn.microsoft.com/en-us/library/t3c3bfhx(VS.71).aspx
Ответ 4
Параметр out
полезен, если вы хотите получить несколько значений результата из метода. Технически вы можете использовать параметр ref
для достижения той же цели, но параметр out
выполняет значительно лучшую работу по передаче намерения. Когда вы используете ref
, неясно, почему вы это делаете, вместо использования out
или вместо использования результата функции. Предположительно, вы намерены изменить переданное значение, но почему вы меняете его, неясно просто из сигнатуры функции.
Ответ 5
Я думаю, что прекрасный пример - int.TryParse()
http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Основная причина, по которой out лучше, чем ref, заключается в том, что вам не нужно назначать фиктивное значение возврату var перед вызовом (даже неявно).
Итак, out сообщает вам и компилятору: "Этот var будет назначен внутри метода. И начальное значение var, если оно есть, даже не будет рассмотрено".
Ответ 6
Основное различие между ними состоит в том, что если мы используем ref, тогда мы должны инициализировать это перед вызовом, и необязательно присваивать значение нашей переменной ref в нашем методе.
Однако для методов out нам не нужно явно их инициализировать, но в нашем методе нам нужно присвоить ему какое-то значение, иначе они будут генерировать ошибку времени компиляции.