Почему руководящие принципы .Net Framework рекомендуют не использовать аргументы ref / out? - PullRequest
9 голосов
/ 18 октября 2008

Видимо, они "сбивают с толку". Это серьезно причина? Вы можете думать о других?

Ответы [ 10 ]

13 голосов
/ 18 октября 2008

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

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

5 голосов
/ 18 октября 2008

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

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

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

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

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

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

2 голосов
/ 18 октября 2008

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

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

(см. Также

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

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

1 голос
/ 19 октября 2008

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

Customer GetCustomerById(int id, out string errorMessage);

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

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

1 голос
/ 18 октября 2008

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

0 голосов
/ 20 октября 2008

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

0 голосов
/ 19 октября 2008

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

0 голосов
/ 18 октября 2008

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

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

0 голосов
/ 18 октября 2008

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

int myValue;
ReadFromSomewhere(ref myValue);

Кому:

int myValue = ReadFromSomewhere();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...