может ли кто-нибудь предложить мне точное использование ключевого слова out в качестве параметра и то, как оно связано для возврата нескольких значений из функции, как в этом POST, меня путают с переменной out с обычной переменной. может ли кто-нибудь мне в этом помочь.
Использование ключевого слова out в c #
Ответы (8)
Это часто сбивает с толку, и я думаю, что документация MSDN на самом деле немного «ясна, только если она уже известна». То есть это правильно, но на самом деле это имеет смысл только в том случае, если вы уже понимаете концепцию.
Вот как я об этом думаю.
Обычный параметр создает копию значения аргумента. Когда ты говоришь:
static int M(int z) { z = z + 1; return z; }
...
int x = 123;
int y = M(x);
Это как вы и сказали:
int x = 123;
int z = x; // make a copy of x
z = z + 1;
int y = z;
Параметр ref или out создает псевдоним для существующей переменной. Когда ты говоришь
static void N(ref int q) { q = q + 1; }
...
int x = 123;
N(x);
Это то же самое, что сказать:
int x = 123;
// MAGIC: q is now an another name for variable x
q = q + 1;
q
и x
- два разных имени, которые относятся к одной и той же переменной. Увеличение q
также увеличивает x
, потому что они одинаковы. z
и x
в предыдущем примере - это два разных имени, которые относятся к двум разным переменным. Увеличение z
не меняет x
.
Подводя итог: «out» и «ref» просто означают «не создавать новую переменную; скорее, временно сделать второе имя для существующей переменной».
Теперь это ясно?
ОБНОВЛЕНИЕ: Я не сказал, в чем разница между "out" и "ref". Отличие простое. На стороне «вызывающего» «ref» должна быть определенно присвоенной переменной перед вызовом метода. «Выхода» быть не должно. На стороне «вызываемого» «ref» может быть прочитан до того, как он будет записан, но «out» должен быть записан до того, как он будет прочитан. Кроме того, необходимо записать «out», прежде чем элемент управления нормально покинет метод.
out
на ref
.
- person phoog; 10.10.2011
документация MSDN уже отлично справляется. объясняя это:
Ключевое слово out заставляет аргументы передаваться по ссылке. Это похоже на ключевое слово ref, за исключением того, что ref требует, чтобы переменная была инициализирована перед передачей. Чтобы использовать параметр out, как определение метода, так и вызывающий метод должны явно использовать ключевое слово out. Например:
class OutExample
{
static void Method(out int i)
{
i = 44;
}
static void Main()
{
int value;
Method(out value);
// value is now 44
}
}
out
должен быть определенно назначен перед нормальным возвратом метода.
- person phoog; 10.10.2011
Он очень часто используется в шаблоне, который «пытается» получить значение, например:
int result;
if(Int32.TryParse("123", out result))
{
Console.WriteLine(result + 1);
}
Ключевое слово out
следует использовать, если вы хотите: а) разрешить вашей функции изменять определенную переменную из вызывающего стека кода И б) принудительно установить значение этой переменной внутри вашей функции.
В большинстве языков, включенных в C #, вы можете передавать значения двумя способами: по значению и по ссылке.
по значению дает методу копию ваших данных, поэтому изменение данных не повлияет на исходные данные
по ссылке по существу дает методу адрес памяти ваших данных, поэтому, если метод изменяет данные, он изменяет оригинал.
Out - это особый тип ссылки, поскольку вам не нужно инициализировать переменную перед вызовом метода, ее можно вызвать с переданным значением null. И она ДОЛЖНА быть установлена методом.
Вы можете думать об этом по-другому (с точки зрения внешнего кода):
val = только чтение
ref = чтение / запись
out = только запись.
http://msdn.microsoft.com/en-us/library/t3c3bfhx(v=vs.80).aspx
Ключевое слово out
хорошо, если вы хотите вернуть несколько значений предопределенных типов (например, int
, List<string>
и DateTime
), и вы не хотите создавать новый класс только для этой цели.
Ok,
давайте посмотрим на обычный шаблон для такого рода функций - TrySomething
. Предположим, у вас есть функция, которая может успешно дать вам значение или нет, но вы не будете использовать для этого исключение, потому что вам не нужны накладные расходы или это обычная черта. Затем вы обычно возвращаете true
, если метод завершился успешно, и false
, если нет. Но куда бы вы поместили свое выходное значение?
Один из возможных ответов - использовать такой параметр out
:
bool TrySomething(MyInputType input, out MyOutputType output)
{
output = default(MyOutputType);
/* ... Try getting the answer ... */
if (!successful)
return false;
output = successfulOutput;
return true;
}
Примечание. Или вы можете подумать об использовании Tuple<bool,MyOutputType>
, и действительно, F # интерпретирует приведенный выше шаблон как приводящий к появлению такого кортежа.