Да - разница между 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
указывает, что значение будет выходить из метода (при условии, что нет никаких исключений) и что вам не нужно иметь значение для начала.
Одна из рекомендаций, которые я сделал для C # 5 (я понятия не имею, будет ли он задействован или нет), заключается в том, что метод с параметром out
должен рассматриваться как метод, возвращающий кортеж значений. В сочетании с улучшенной поддержкой кортежей это может означать, что мы можем сделать что-то вроде этого:
var (ok, value) = int.TryParse(text);
В этом случае ok
и value
будут неявно введены в bool
и int
соответственно. Таким образом, становится ясно, что входит в метод (text
) и что выходит (две части информации: ok
и value
).
Это просто было бы недоступно, если бы int.TryParse
использовал вместо этого параметр ref
- так как компилятор не может знать, собирается ли он на самом деле заботиться о начальном значении параметра ref
.