Вопрос

Рассмотрим функцию, которая возвращает два значения.Мы можем написать:

родовое слово

Какой из них является наилучшим и почему?

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

Решение

У каждого из них есть свои плюсы и минусы.

Параметры Out являются быстрыми и дешевыми, но требуют, чтобы вы передавали переменную и полагались на мутацию.Практически невозможно правильно использовать параметр out в LINQ.

Кортежи создают давление при сборе и не являются самодокументированными."Item1" не очень информативный.

Пользовательские структуры могут медленно копироваться, если они большие, но они самодокументируются и эффективны, если они маленькие.Однако также сложно определить целую кучу настраиваемых структур для тривиального использования.

Я был бы склонен к решению нестандартной структуры при прочих равных условиях.Еще лучше - создать функцию, возвращающую только одно значение .Почему вы вообще возвращаете два значения?

ОБНОВЛЕНИЕ. Обратите внимание, что кортежи в C # 7, выпущенные через шесть лет после написания этой статьи, являются типами значений и, следовательно, с меньшей вероятностью будут создавать давление сбора.

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

Я думаю, что ответ зависит от семантики того, что делает функция, и отношения между двумя значениями.

Например, методы TryParse принимают параметр out, чтобы принять проанализированное значение, и возвращают код bool, чтобы указать, удалось ли выполнить синтаксический анализ.Эти два значения на самом деле не принадлежат друг другу, поэтому семантически имеет больше смысла, а цель кода легче читать, использовать параметр out.

Если, однако, ваша функция возвращает координаты X / Y некоторого объекта на экране, тогда два значения семантически принадлежат друг другу, и было бы лучше использовать общий код кода.

Лично я бы избегал использования кода struct для всего, что будет видно внешнему коду из-за неудобного синтаксиса для получения членов.

В дополнение к предыдущим ответам, C # 7 предоставляет кортежи типов значений, в отличие от System.Tuple, который является ссылочным типом, а также предлагает улучшенную семантику.

Вы все равно можете оставить их безымянными и использовать синтаксис .Item*:

родовое слово

Но что действительно мощно в этой новой функции, так это возможность иметь именованные кортежи.Итак, мы могли бы переписать вышесказанное так:

родовое слово

Также поддерживается деструктуризация:

(string firstName, string lastName, int age) = getPerson()

Я буду использовать подход с использованием параметра Out, потому что во втором подходе вам потребуется создать объект класса Tuple, а затем добавить к нему значение, что, на мой взгляд, является дорогостоящей операцией по сравнению с возвратом значения в параметре out.Хотя, если вы хотите вернуть несколько значений в классе кортежей (что на самом деле невозможно сделать, просто вернув один выходной параметр), я выберу второй подход.

Вы не упомянули еще об одном варианте, который использует собственный класс вместо структуры.Если данные имеют связанную с ними семантику, с которой могут работать функции, или если размер экземпляра достаточно велик (как правило,> 16 байт), предпочтительным может быть специальный класс. Использование out в общедоступном API не рекомендуется, поскольку оно связано с указателями и требует понимания того, как работают ссылочные типы.

https://msdn.microsoft.com/en-us/library/ms182131.aspx

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

Не существует "передовой практики".Это то, что вам удобно и что лучше всего работает в вашей ситуации.Пока вы согласны с этим, нет никаких проблем ни с одним из опубликованных вами решений.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top