Синтаксис C # - Ваша предпочтительная практика для получения 2 или 3 ответов из метода

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

Вопрос

Мне просто интересно, как другие разработчики решают эту проблему получения 2 или 3 ответов от метода.

1) возвращает объект[]
2) возвращает пользовательский класс
3) используйте ключевое слово out или ref для нескольких переменных
4) напишите или позаимствуйте (F #) простой Кортеж<> универсальный класс
http://slideguitarist.blogspot.com/2008/02/whats-f-tuple.html

Сейчас я работаю над некоторым кодом, который обновляет данные.Из метода, который выполняет обновление, я хотел бы передать обратно (1) Время начала обновления и (2) Время окончания обновления.
Позже я, возможно, захочу передать обратно третье значение.

Мысли?Есть какие-нибудь рекомендации из проектов .NET с открытым исходным кодом по этой теме?

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

Решение

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

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

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

Это полностью зависит от того, каковы будут результаты.Если они связаны друг с другом, я обычно создаю пользовательский класс.

Если они на самом деле не связаны, я бы либо использовал параметр out, либо разделил метод.Если метод хочет вернуть три несвязанных элемента, он, вероятно, делает слишком много.Исключением из этого является случай, когда вы общаетесь через границу веб-сервиса или что-то еще, где "более чистый" API может быть слишком разговорчивым.

На двоих, обычно 4)

Более того, 2)

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

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

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

Я использую out, если это только 1 или 2 дополнительные переменные (например, функция возвращает bool, который является фактическим важным результатом, но также long в качестве параметра out, чтобы возвращать, как долго выполнялась функция, для целей ведения журнала).

Для чего-то более сложного я обычно создаю пользовательскую структуру / класс.

Я думаю, что наиболее распространенным способом, которым программист C # сделал бы это, было бы обернуть элементы, которые вы хотите вернуть, в отдельный класс.Это обеспечило бы вам максимальную гибкость в будущем, ИМХО.

Это зависит от обстоятельств.Для внутреннего API я обычно выбираю самый простой вариант.Как правило, это исключено.

Для общедоступного API пользовательский класс обычно имеет больше смысла, но если это что-то довольно примитивное или естественным результатом функции является логическое значение (например, *.TryParse), я буду придерживаться параметра out .Вы также можете создать пользовательский класс с неявным приведением к bool, но обычно это просто странно.

Для вашей конкретной ситуации простой неизменяемый класс DateRange кажется мне наиболее подходящим.Вы можете легко добавить это новое значение, не беспокоя существующих пользователей.

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

Некоторые люди используют KeyValuePair для двух значений.Однако это не очень здорово, потому что это просто маркирует две вещи как Key и Value.Не очень описательно.Кроме того, было бы серьезно полезно добавить это:

public static class KeyValuePair
{
    public static KeyValuePair<K, V> Make(K k, V v) 
    { 
        return new KeyValuePair<K, V>(k, v); 
    }
}

Избавляет вас от необходимости указывать типы при их создании.Универсальные методы могут определять типы, а универсальные конструкторы классов - нет.

Для вашего сценария вы можете захотеть определить общий класс Range{T} (с проверкой достоверности диапазона).

Если метод является частным, то я обычно использую кортежи из моя вспомогательная библиотека.Общедоступные или защищенные методы, как правило, всегда заслуживают отдельного рассмотрения.

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

Если 2, то Пара.

Если больше 2-х классов.

Другим решением является возврат словаря ссылок на именованные объекты.Для меня это в значительной степени эквивалентно использованию пользовательского возвращаемого класса, но без беспорядка.(И используя RTTI и reflection, это так же безопасно для типов, как и любое другое решение, хотя и динамически.)

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

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

Для общедоступных / защищенных / внутренних методов (т.е.не частный), я использую либо параметр out, либо пользовательский класс.

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

Если результаты ориентированы на последовательность (т.е.верните 3 клиента, которые должны быть обработаны), затем я обычно возвращаю какую-то коллекцию.

В остальном я обычно просто использую пользовательский класс.

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

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