C # предоставляет ключевое слово ref
and out
для аргументов, передаваемых по ссылке. Семантика двух очень похожа. Единственная разница заключается в инициализации переменной:
ref
требует, чтобы переменная была инициализирована перед передачей функции,out
нет.out
требует, чтобы переменная была инициализирована внутри функции,ref
нет.
Варианты использования этих двух ключевых слов также почти одинаковы, и их слишком частое использование, как я полагаю, считается запахом кода (хотя существуют допустимые варианты использования, такие как шаблоны TryParse
and TryGetValue
).
Из-за этого кто-то может объяснить, почему в C # есть два очень похожих инструмента для столь узких вариантов использования?
Также в MSDN указано, что у них другое поведение во время выполнения:
Хотя ключевые слова ref и out вызывают различное поведение во время выполнения, они не считаются частью сигнатуры метода во время компиляции.
Чем отличается их поведение во время выполнения?
Вывод
Оба ответа выглядят правильно, спасибо вам обоим. Я принял Jmoreno , потому что это более явно.
источник
ref
в C ++; указатели на указатель объекта (или примитив) в вопросе. т.е.Int32.TryParse(myStr, out myInt)
(C #) «выполняется» так же, какint32_tryParse(myStr, &myInt)
(C); единственное отличие заключается в том, что компилятор налагает некоторые ограничения на предотвращение ошибок. (Я не собираюсь публиковать это как ответ, потому что я могу ошибаться из-за того, как это работает за кулисами, но я думаю, что это работает [потому что это имеет смысл])Ответы:
В то время, когда был задан этот вопрос, статья MSDN была немного неверной (с тех пор она была исправлена ). Вместо «вызывать другое поведение» оно должно быть «требует другого поведения».
В частности, компилятор обеспечивает разные требования для двух ключевых слов, хотя для включения поведения используется один и тот же механизм (IL).
источник
out
параметра или не присваиваниеref
параметра, но IL, который он выдает, в любом случае является просто ссылкой. Это верно?out T
иref T
оказаны одинаково на других языках CLI , таких как VB.NET или C ++ / CLI.Вот интересная рецензия на тему, которая может ответить на ваш вопрос:
http://www.dotnetperls.com/ref
достопримечательность:
«Разница между ref и out не в Common Language Runtime, а в самом языке C #».
Обновить:
Старший разработчик моей работы только что подтвердил ответ @ jmoreno, поэтому обязательно прочтите его !.
источник
string
общего со всем этим?Время выполнения ? Абсолютно нет. Вы не можете перегружать метод с одинаковыми параметрами, отличающимися только ключевым словом ref или out.
Попробуйте скомпилировать это, и вы получите ошибку компиляции «Метод с такой же подписью уже объявлен»:
Чтобы ответить на этот вопрос: «... почему в C # есть два очень похожих инструмента для столь узких вариантов использования?»
С точки зрения читабельности кода и API существует огромная разница. Как потребитель API я знаю, что при использовании «out» API не зависит от параметра out. Как разработчик API, я предпочитаю «out» и использую «ref» только тогда, когда это абсолютно НЕОБХОДИМО! Смотрите эту ссылку для большой дискуссии:
/programming/1516876/when-to-use-ref-vs-out
Вспомогательная информация: я скомпилировал следующий метод и разобрал его. Я использовал ключевые слова ref и out (out в этом примере), но код сборки не изменился, за исключением ссылки на адрес, как и следовало ожидать:
00000000 толчок EBP
00000001 мов EBP, ESP
00000003 толчок еди
00000004 толчок еси
00000005 толчок EBX
00000006 суб особ, 34h
00000009 XOR EAX, EAX
0000000b мов DWORD PTR [EBP-10h], EAX
0000000e мов DWORD PTR [EBP-1Ch], EAX
00000011 mov dword ptr [ebp-3Ch], ecx
00000014 mov dword ptr [ebp-40h], edx
00000017 cmp dword ptr ds: [008B1710h], 0
0000001e je 00000025
00000020 вызов 6E6B601E
00000025 nop
param = 0;
00000026 mov eax, dword ptr [ebp-40h]
00000029 xor edx, edx
0000002b mov dword ptr [eax], edx
}
0000002d nop
0000002e lea esp, [ebp-0Ch]
00000031 pop ebx
00000032 pop esi
00000033 pop
edi 00000034 pop ebp
00000035 ret
Я правильно читаю сборку?
источник