Если мы хотим получить значение из метода, мы можем использовать любое возвращаемое значение, например так:
public int GetValue();
или:
public void GetValue(out int x);
Я не очень понимаю разницу между ними, и поэтому не знаю, что лучше. Можете ли вы объяснить мне это?
Спасибо.
Tuple
если хотите, но общий консенсус заключается в том, что если вам нужно вернуть более одной вещи, вещи обычно как-то связаны, и это отношение обычно лучше всего выражать в виде класса.return Tuple.Create(x, y, z);
Разве это не уродливо. Кроме того, уже поздно их вводить на уровне языка. Причина, по которой я не буду создавать класс для возврата значений из параметра ref / out, заключается в том, что параметры ref / out действительно имеют смысл только для больших изменяемых структур (например, матриц) или необязательных значений, а последний является дискуссионным.Tuple<>
и C # кортежи !. Я просто хотел, чтобы C # позволял возвращать анонимные типы из методов с выводимым типом компилятора (какauto
в Dlang).Ответы:
Возвращаемые значения почти всегда являются правильным выбором, когда метод не должен больше ничего возвращать. (На самом деле, я не могу думать о каких - либо случаях , когда я когда - либо хотят аннулировать метод с
out
параметром, если у меня был выбор. C # 7 - хDeconstruct
методах языка при поддержке деконструкции действует как очень, очень редкое исключение из этого правила .)Помимо всего прочего, он не дает вызывающей стороне объявлять переменную отдельно:
против
Выходные значения также предотвращают цепочку методов следующим образом:
(Действительно, это также одна из проблем с установщиками свойств, и именно поэтому шаблон компоновщика использует методы, которые возвращают компоновщик, например,
myStringBuilder.Append(xxx).Append(yyy)
.)Кроме того, параметры вывода немного сложнее использовать с отражением и обычно также усложняют тестирование. (Обычно делается больше усилий для упрощения имитации возвращаемых значений, чем параметров). В принципе, я ничего не могу придумать, чтобы им было легче ...
Возвращаемые значения FTW.
РЕДАКТИРОВАТЬ: с точки зрения того, что происходит ...
В основном, когда вы передаете аргумент для параметра out, вы должны передать переменную. (Элементы массива также классифицируются как переменные.) В методе, который вы вызываете, нет «новой» переменной в стеке для параметра - он использует вашу переменную для хранения. Любые изменения в переменной сразу видны. Вот пример, показывающий разницу:
Полученные результаты:
Разница заключается в шаге «post» - т.е. после изменения локальной переменной или параметра. В тесте ReturnValue это не имеет значения для статической
value
переменной. В тесте OutParametervalue
переменная изменяется строкойtmp = 10;
источник
Dictionary.TryGetValue
здесь не применим, так как это не пустой метод. Можете ли вы объяснить, почему вы хотитеout
параметр вместо возвращаемого значения? (Даже дляTryGetValue
, я бы предпочел возвращаемое значение, которое содержит всю выходную информацию лично. См. NodaTime'sParseResult<T>
для примера того, как я разработал бы это.)out
параметром вы просто не можете ничего сделать со значением.Что лучше, зависит от вашей конкретной ситуации. Одна из причин
out
существует для облегчения возврата нескольких значений из одного вызова метода:Так что одно по определению не лучше другого. Но обычно вы хотите использовать простой возврат, если, например, у вас нет описанной выше ситуации.
РЕДАКТИРОВАТЬ: это образец, демонстрирующий одну из причин, по которой ключевое слово существует. Вышеизложенное ни в коем случае нельзя считать лучшей практикой.
источник
Как правило, вы должны предпочесть возвращаемое значение перед выходным параметром. Выходные параметры - неизбежное зло, если вы обнаружите, что пишете код, который должен сделать 2 вещи. Хорошим примером этого является шаблон Try (например, Int32.TryParse).
Давайте рассмотрим, что должен делать вызывающий из ваших двух методов. Для первого примера я могу написать это ...
Обратите внимание, что я могу объявить переменную и назначить ее через ваш метод в одну строку. Для второго примера это выглядит так ...
Теперь я вынужден объявить свою переменную заранее и написать код в две строки.
Обновить
При задании таких вопросов лучше всего ознакомиться с Руководством по разработке .NET Framework. Если у вас есть книжная версия, вы можете увидеть аннотации Андерса Хейлсберга и других на эту тему (стр. 184-185), но онлайн-версия здесь ...
http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx
Если вы обнаружите, что вам нужно вернуть две вещи из API, тогда лучше заключить их в структуру / класс, чем в out-параметр.
источник
Есть одна причина использовать
out
параметр, который еще не был упомянут: вызывающий метод обязан его получить. Если ваш метод выдает значение, которое вызывающая сторона не должна отбрасывать, то этоout
заставляет вызывающую функцию специально принять его:Конечно, вызывающая сторона все еще может игнорировать значение в
out
параметре, но вы обратили на это внимание.Это редкая необходимость; чаще вы должны использовать исключение для реальной проблемы или возвращать объект с информацией о состоянии для «FYI», но могут быть обстоятельства, когда это важно.
источник
Это предпочтение в основном
Я предпочитаю возвраты, и если у вас есть несколько возвратов, вы можете заключить их в Resto DTO
источник
Вы можете иметь только одно возвращаемое значение, тогда как у вас может быть несколько выходных параметров.
Вам нужно только рассмотреть параметры в этих случаях.
Однако, если вам нужно вернуть более одного параметра из вашего метода, вы, вероятно, захотите посмотреть, что вы возвращаете из ОО-подхода, и подумать, лучше ли вам возвращать объект или структуру с этими параметрами. Поэтому вы снова возвращаетесь к возвращаемому значению.
источник
Вы должны почти всегда использовать возвращаемое значение. '
out
' параметры создают немного трения ко многим API, композиционности и т. д.Самое примечательное исключение, которое приходит на ум, - это когда вы хотите вернуть несколько значений (.Net Framework не имеет кортежей до 4.0), например, с
TryParse
шаблоном.источник
Я бы предпочел следующее вместо одного из них в этом простом примере.
Но они все очень похожи. Обычно можно использовать «out», только если им нужно передать несколько значений обратно из метода. Если вы хотите отправить значение в метод и из него, выберите «ref». Мой метод лучше всего подходит, если вы только возвращаете значение, но если вы хотите передать параметр и получить значение обратно, вы, вероятно, выбрали бы ваш первый выбор.
источник
Я думаю, что один из немногих сценариев, в которых это было бы полезно, был бы при работе с неуправляемой памятью, и вы хотите сделать очевидным, что «возвращаемое» значение следует удалять вручную, а не ожидать, что оно будет удалено само по себе. ,
источник
Кроме того, возвращаемые значения совместимы с парадигмами асинхронного проектирования.
Вы не можете назначить функцию «асинхронная», если она использует параметры ref или out.
Таким образом, возвращаемые значения позволяют создавать цепочки методов, более чистый синтаксис (устраняя необходимость для вызывающей стороны объявлять дополнительные переменные) и позволяют создавать асинхронные схемы без существенных изменений в будущем.
источник
Оба они имеют различное назначение и не обрабатываются одинаково компилятором. Если ваш метод должен вернуть значение, вы должны использовать return. Out используется, когда ваш метод должен возвращать несколько значений.
Если вы используете return, то данные сначала записываются в стек методов, а затем в вызывающий метод. Хотя в случае out он напрямую записывается в стек вызывающих методов. Не уверен, есть ли еще различия.
источник
Как уже говорили другие: возвращаемое значение, а не парам.
Могу ли я порекомендовать вам книгу «Руководство по проектированию рамок» (2-е изд)? Страницы 184-185 раскрывают причины, по которым следует избегать использования параметров. Вся книга будет направлять вас в правильном направлении по всем вопросам кодирования .NET.
В союзе с Framework Design Guidelines используется инструмент статического анализа FxCop. Вы найдете это на сайтах Microsoft для бесплатной загрузки. Запустите это на своем скомпилированном коде и посмотрите, что он говорит. Если он жалуется на сотни и сотни вещей ... не паникуйте! Посмотрите спокойно и внимательно на то, что говорится о каждом конкретном случае. Не спешите исправлять вещи как можно скорее. Учитесь на том, что это говорит вам. Вы будете поставлены на путь к мастерству.
источник
Использование ключевого слова out с возвращаемым типом bool иногда может уменьшить раздувание кода и повысить читабельность. (Прежде всего, когда дополнительная информация в выходном параметре часто игнорируется.) Например:
против:
источник
Там нет никакой разницы. Выходные параметры в C # позволяют методу возвращать более одного значения, вот и все.
Однако есть небольшие отличия, но они не очень важны:
Использование параметра out заставит вас использовать две строки, такие как:
в то время как использование возвращаемого значения позволит вам сделать это в одну строку:
Другое отличие (корректное только для типов значений и только в том случае, если C # не включает функцию) в том, что использование возвращаемого значения обязательно создаст копию значения при возврате функции, тогда как использование параметра OUT не обязательно сделает это.
источник
out более полезен, когда вы пытаетесь вернуть объект, который вы объявляете в методе.
пример
источник
возвращаемое значение - это нормальное значение, которое возвращается вашим методом.
Где в качестве параметра out , well out и ref являются 2 ключевыми словами C #, они позволяют передавать переменные в качестве ссылки .
Большая разница между рефами и отказом есть ссылка должна быть инициализирована до и вне этого не
источник
Я подозреваю, что не собираюсь заглядывать в этот вопрос, но я очень опытный программист, и я надеюсь, что некоторые из более открытых читателей обратят внимание.
Я считаю, что объектно-ориентированные языки программирования лучше подходят для того, чтобы их процедуры возврата значений (VRP) были детерминированными и чистыми.
«VRP» - это современное академическое название для функции, которая вызывается как часть выражения и имеет возвращаемое значение, которое условно заменяет вызов во время вычисления выражения. Например, в таком утверждении, как
x = 1 + f(y)
функцияf
, выступает в качестве VRP.«Детерминистический» означает, что результат функции зависит только от значений ее параметров. Если вы вызовете его снова с теми же значениями параметров, вы обязательно получите тот же результат.
«Чистый» означает отсутствие побочных эффектов: вызов функции ничего не делает, кроме вычисления результата. Это может быть интерпретировано не значит не важно побочных эффектов на практике, поэтому, если VRP выводит сообщение отладки каждый раз, когда оно вызывается, например, это, вероятно, можно игнорировать.
Таким образом, если в C # ваша функция не является детерминированной и чистой, я говорю, что вы должны сделать ее
void
функцией (другими словами, не VRP), и любое значение, которое она должна вернуть, должно быть возвращено либо вout
a, либо в a.ref
параметре, параметре.Например, если у вас есть функция для удаления некоторых строк из таблицы базы данных, и вы хотите, чтобы она возвращала количество удаленных строк, вы должны объявить ее примерно так:
public void DeleteBasketItems(BasketItemCategory category, out int count);
Если вы иногда хотите вызвать эту функцию, но не получите
count
, вы всегда можете объявить перегрузку.Возможно, вы захотите узнать, почему этот стиль лучше подходит для объектно-ориентированного программирования. В целом, он вписывается в стиль программирования, который можно (немного неточно) назвать «процедурным программированием», и это стиль процедурного программирования, который лучше подходит для объектно-ориентированного программирования.
Зачем? Классическая модель объектов состоит в том, что они имеют свойства (или атрибуты), и вы запрашиваете и манипулируете объектом (главным образом) посредством чтения и обновления этих свойств. Стиль процедурного программирования облегчает эту задачу, поскольку вы можете выполнять произвольный код между операциями, которые получают и устанавливают свойства.
Недостатком процедурного программирования является то, что, поскольку вы можете выполнять произвольный код повсюду, вы можете получить очень тупые и уязвимые для взаимодействия взаимодействия через глобальные переменные и побочные эффекты.
Итак, довольно просто, хорошей практикой является сигнализировать кому-то, читающему ваш код, что у функции могут быть побочные эффекты, если она не возвращает значения.
источник
_
символ сброса, чтобы игнорировать параметр out, например: DeleteBasketItems (category, out _);