Возврат нескольких значений из метода в C#
В этом посте будет обсуждаться, как вернуть несколько значений из метода в C#.
В соответствии со спецификацией языка C# возврат нескольких значений из метода невозможен. Используя некоторые другие функции, предлагаемые C#, мы можем возвращать несколько значений вызывающему методу. В этом посте представлен обзор некоторых доступных альтернатив для достижения этой цели.
1. Использование параметров ссылки
Мы можем использовать ключевое слово ссылки чтобы вернуть значение вызывающей стороне по ссылке. Мы можем использовать его для возврата нескольких значений из метода, как показано ниже:
Как вернуть список из метода в C#
Как вернуть список, содержащий результат LINQ to SQLquery? Я пытаюсь эту реализацию, но я получил эту ошибку.
Невозможно неявно преобразовать тип ‘System.Collections.Generic.List<AnonymousType#1>’ в ‘System.Collections.Generic.List<object>
Любая помощь будет оценена по достоинству.
Ответы (2)
Анонимные типы специально разработаны для использования исключительно в той области, в которой они определены. Если вы хотите вернуть результаты запроса из этого метода, вы должны создать новый именованный тип для представления результатов вашего запроса и выбрать экземпляры этого именованного типа, а не экземпляры анонимного типа.
Вы не можете вернуть список, где T является анонимным типом; вам нужно вернуть известный тип. Вы можете создать класс
Как можно безопасно вернуть List <T> из метода / свойства, объявленного как IEnumerable <T>?
Скажем, у меня есть свойство IEnumerable<int> , поддерживаемое полем List<int> , поэтому я могу изменить коллекцию из класса, но она публично отображается как доступная только для чтения.
Но с таким кодом вы можете легко вернуть объект, полученный из свойства, обратно в List<int> и изменить его:
Вопрос: , что лучше (лучше всего читать, проще всего писать, без потери производительности), чтобы избежать этого?
Я могу придумать по крайней мере 4 решения, но они не идеальны:
foreach и yield return :
— действительно раздражает писать и читать.
+ вызовет исключение, когда кто-то попытается изменить возвращенную коллекцию
+ не создает копию всей коллекции.
+ Пользователь по-прежнему может изменять извлеченную коллекцию, но это не та же коллекция, которую мы модифицируем внутри класса, поэтому нам все равно.
— создает копию всей коллекции, что может вызвать проблемы при большой коллекции.
Пользовательский класс оболочки.
+ не нужно клонировать коллекцию
—, когда вы используете его как источник запросов LINQ, некоторые методы не будут использовать ICollection.Count , потому что вы его не открываете.
Есть ли лучший способ сделать это?
4 ответа
Вопрос: что лучше (лучше всего читать, проще всего писать, без потери производительности), чтобы избежать этого?
В общем, я не пытаюсь этого избежать. Потребитель моего API должен использовать тип, который я выставляю, и если они этого не делают, любые ошибки, вызванные их ошибкой, а не мои. Таким образом, мне все равно, будут ли они передавать данные таким образом — когда я изменяю свое внутреннее представление, и они получают исключения исключения, что их проблема.
Если у вас есть проблема с безопасностью, я бы, скорее всего, использовал AsReadOnly . Это фактически самодокументируется и не имеет реальных недостатков (кроме небольшого выделения для обертки, поскольку нет копии данных, вы получаете значимые исключения при модификации и т.д.). Нет никакого реального недостатка в этом против создания собственной пользовательской оболочки, а пользовательская оболочка означает больше кода для тестирования и обслуживания.
В общем, я лично стараюсь избегать копирования без причины. Это исключало бы ToList() как вариант в целом. Использование итератора (ваш первый вариант) не так плохо, хотя на самом деле он не дает много преимуществ по сравнению с ReadOnlyCollection<T> .
В общем, я не в лагере. Если я дам вам IEnumerable, и вы отбросите его на что-то еще, то это тот, кто нарушил контракт, и это не моя вина, если что-то сломается. Если бы я оказался в положении, когда мне действительно нужно было защитить клиента от развращения моего состояния, я бы создал метод расширения, например:
Как вернуть list из метода в c
Метод может возвращать значение, какой-либо результат. В примере выше были определены два метода, которые имели тип void . Методы с таким типом не возвращают никакого значения. Они просто выполняют некоторые действия.
Но методы также могут возвращать некоторое значение. Для этого применяется оператор return , после которого идет возвращаемое значение:
Например, определим метод, который возвращает значение типа string :
Метод GetMessage имеет тип string , следовательно, он должен возвратить строку. Поэтому в теле метода используется оператор return , после которого указана возвращаемая строка.
При этом методы, которые в качестве возвращаемого типа имеют любой тип, кроме void , обязательно должны использовать оператор return для возвращения значения. Например, следующее определение метода некорректно:
Также между возвращаемым типом метода и возвращаемым значением после оператора return должно быть соответствие. Например, в следующем случае возвращаемый тип — string , но метод возвращает число (тип int), поэтому такое определение метода некорректно:
Результат методов, который возвращают значение, мы можем присвоить переменным или использовать иным образом в программе:
Метод GetMessage() возвращает значение типа string . Поэтому мы можем присвоить это значение какой-нибудь переменной типа string: string message = GetMessage();
Либо даже передать в качестве значения параметру другого метода:
В вызове PrintMessage(GetMessage()) сначада вызывается метод GetMessage() и его результат передается параметру message метода PrintMessage
После оператора return также можно указывать сложные выражения или вызовы других методов, которые возвращают определенный результат. Например, определим метод, который возвращает сумму чисел:
Метод Sum() имеет тип int , следовательно, он должен возвратить значение типа int — целое число. Поэтому в теле метода используется оператор return , после которого указано возвращаемое число (в данном случае результат суммы переменных x и y).
Сокращенная версия методов с результатом
Также мы можем сокращать методы, которые возвращают значение:
аналогичен следующему методу:
аналогичен следующему методу:
Выход из метода
Оператор return не только возвращает значение, но и производит выход из метода. Поэтому он должен определяться после остальных инструкций. Например:
С точки зрения синтаксиса данный метод корректен, однако его инструкция Console.WriteLine(«After return») не имеет смысла — она никогда не выполнится, так как до ее выполнения оператор return возвратит значение и произведет выход из метода.
Однако мы можем использовать оператор return и в методах с типом void . В этом случае после оператора return не ставится никакого возвращаемого значения (ведь метод ничего не возвращает). Типичная ситуация — в зависимости от опеределенных условий произвести выход из метода:
Здесь метод PrintPerson() в качестве параметров принимает имя и возраст пользователя. Однако в методе вначале мы проверяем, соответствует ли возраст некоторому диапазону (меньше 120 и больше 0). Если возраст находится вне этого диапазона, то выводим сообщение о недопустимом возрасте и с помощью оператора return выходим из метода. После этого метод заканчивает свою работу.
Однако если возраст корректен, то выводим информацию о пользователе на консоль. Консольный вывод: