Подтвердить что ты не робот

В каких ситуациях полезны параметры "out" (где "ref" не может использоваться вместо этого)?

Насколько я могу судить, единственным параметром для out является то, что вызывающий может получить несколько возвращаемых значений из одного вызова метода. Но мы можем также получить несколько значений результата, используя ref параметры!

Итак, существуют ли другие ситуации, когда параметры out могут оказаться полезными и где мы не могли бы использовать параметры ref вместо этого?

Спасибо.

4b9b3361

Ответ 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 нам не нужно явно их инициализировать, но в нашем методе нам нужно присвоить ему какое-то значение, иначе они будут генерировать ошибку времени компиляции.