Почему в руководстве .Net framework рекомендуется не использовать аргументы ref / out ?

StackOverflow https://stackoverflow.com/questions/214688

  •  03-07-2019
  •  | 
  •  

Вопрос

Очевидно, они "сбивают с толку".Неужели причина действительно в этом?Можете ли вы вспомнить какие-нибудь другие?

Это было полезно?

Решение

Видели ли вы, сколько разработчиков на самом деле не понимают ref / out?

Я использую их там, где они действительно необходимы, но не иначе. Обычно они полезны только в том случае, если вы хотите эффективно вернуть два или более значений - в этом случае стоит хотя бы подумать о том, есть ли способ заставить метод делать только одну вещь вместо этого. Иногда использование ref / out является наиболее подходящим подходом - различные методы TryParse и т. Д.

Другие советы

На мой взгляд, они считаются запахом кода, потому что в целом есть гораздо лучший вариант:возвращает объект.

Если вы заметили, в библиотеке .NET они используются только в некоторых особых случаях, а именно попробуйте проанализировать-например, сценарии, в которых:

  • возврат класса будет означать блокировку типа значения
  • контракт метода требует, чтобы он был быстрым, и поэтому упаковка / распаковка не является жизнеспособным вариантом.

ref / out автоматически означает изменчивость, и функциональное программирование с неизменяемыми значениями в настоящее время очень популярно. Попробуйте вставить вызов Dictionary.TryGetValue в запрос LINQ. API требует объявления переменных и разрушает любую «беглость» в API.

Это не значит, что это "причина", но это пример "причины".

(см. также

http://lorgonblog.spaces.live.com/blog /cns!701679AD17B6D310!181.entry

для комментариев о том, как функциональные языки работают с такими API.)

Запутанность, вероятно, лучшая причина. Путаница означает снижение ремонтопригодности и повышение вероятности появления незначительных ошибок. Я вижу их в том же виде, что и "Перейти к". утверждение потока управления. Хотя сам по себе он не является плохим, он привел к тому, что многие программы стали не поддающимися чтению и пониманию на протяжении десятилетий.

Держитесь подальше от всего, что может сделать ваш код более запутанным, чем должно быть.

Сказав это, эти ключевые слова существуют, вероятно, потому, что разработчики фреймворка видели необходимость в таких вещах. Используйте их, если нет подходящего обходного пути, но избегайте их, когда можете.

ref / out также не работает с " Func " делегаты, так что эти API стилей менее комбинируемы / повторно используются с некоторыми другими API, которые используют делегаты.

Я просто считаю, что ref / out полезен, когда аргументы фиксируют состояние выполнения в целевом методе, а не захватывают возвращаемые данные. Рассмотрим сценарий, когда вы хотите получить сообщение об ошибке от службы, которая возвращает объект Customer.

Customer GetCustomerById(int id, out string errorMessage);

Если этот метод завершится ошибкой, вы, вероятно, вернете нулевой объект Customer или сгенерируете исключение. Однако, если я хочу узнать причину ошибки (проверка? База данных?), Я бы использовал аргумент out. Аргумент errorMessage здесь не имеет ничего общего с данными, просто используется для определения того, что не так с выполнением метода.

Лично, если у меня есть метод, который должен возвращать два или более важных данных / значения, я бы переосмыслил дизайн своего кода.

Мне сказали, что у 1.0 GC были проблемы при использовании ref / out. GC в 2.0 (и, вероятно, не в 1.1) также не имеет этих проблем, поэтому я обычно предполагаю, что это теперь бесполезное наследие.

@TraumaPony Было бы неплохо, если бы вы предоставили нам источник (URL или что-то еще) для этого руководства .NET framework.

Вы должны возвращать объекты - это, вероятно, наиболее вероятная причина, по которой они предлагают не использовать ref или out.

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

Разве сложность кода не является достаточной причиной?Сравнить:

int myValue;
ReadFromSomewhere(ref myValue);

Для:

int myValue = ReadFromSomewhere();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top