Есть ли способ вернуть более одного целого числа из метода?

У меня есть такой метод:

private double GetHeight()
{
    return 2;
}

Но я хотел бы иметь возможность вернуть два разных числа, например 2 и 3. Можно ли как-то сделать это на С#?

вернуть массив, если вам нужно больше значений

Shubham 08.04.2019 10:49
Этот наверное именно то, что вам нужно
Jordi 08.04.2019 10:51

для ясности: всегда ли ваш метод возвращает такое же количество возвращаемых значений (каждое с определенным семантическим значением) - или количество возвращаемых значений динамичный, т.е. иногда это будет 1 (или, может быть, даже ноль), а иногда это может быть 20? Это очень важно. Для сценария с фиксированным числом: любой из кортежных ответов хорош; для динамического сценария: подходы массива/списка хороши.

Marc Gravell 08.04.2019 11:00

Откуда у этого вопроса столько голосов? Вопрос требует значительных усилий, и простой поиск в Интернете дал бы ответ stackoverflow.com/help/как спросить.

Denny 08.04.2019 14:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
28
4
1 626
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Да ValueTuple/Именованный кортеж (доступно в C# 7.0). Преимущество в том, что он самый лаконичный, неизменяемый и простой в построении.

The ValueTuple struct has fields named Item1, Item2, Item3, and so on, similar to the properties defined in the existing Tuple types.

However, when you initialize a tuple, you can use new language features that give better names to each field. Doing so creates a named tuple. Named tuples still have elements named Item1, Item2, Item3 and so on. But they also have synonyms for any of those elements that you have named. You create a named tuple by specifying the names for each element.

private (double first, double second) GetHeight()
{
   return (1,2);
}

...

var result = ViaNamedValueTuple();
Console.WriteLine($"{result.first}, {result.second}");

var (first, second) = ViaNamedValueTuple();
Console.WriteLine($"{first}, {second}");

Классический кортеж

Тип кортежа C#

The .NET Framework already has generic Tuple classes. These classes, however, had two major limitations. For one, the Tuple classes named their properties Item1, Item2, and so on. Those names carry no semantic information. Using these Tuple types does not enable communicating the meaning of each of the properties. The new language features enable you to declare and use semantically meaningful names for the elements in a tuple.

public Tuple<int, int> ViaClassicTuple()
{
   return new Tuple<int, int>(1,2);
}

...

var tuple = ViaClassicTuple();
Console.WriteLine($"{tuple.Item1}, {tuple.Item2}");

Классическая структура

структура (справочник по C#)

A struct type is a value type that is typically used to encapsulate small groups of related variables, such as the coordinates of a rectangle or the characteristics of an item in an inventory.

public struct ClassicStruct
{
   public int First { get; set; }
   public int Second { get; set; }
   public ClassicStruct(int first, int second)
   {
      First = first;
      Second = second;
   }
}

...

public ClassicStruct ViaClassicStruct()
{
   return new ClassicStruct(1, 2);
}

... 

var classicStruct = ViaClassicStruct();
Console.WriteLine($"{classicStruct.First}, {classicStruct.Second}");

Структура только для чтения

только для чтения (справочник по C#)

The readonly modifier on a struct definition declares that the struct is immutable. Every instance field of the struct must be marked readonly, as shown in the following example:

public readonly struct ReadonlyStruct
{
   public int First { get; }
   public int Second { get; }
   public ReadonlyStruct(int first, int second)
   {
      First = first;
      Second = second;
   }
}

...

public ReadonlyStruct ViaReadonlyStruct()
{
   return new ReadonlyStruct(1, 2);
}

...


var readonlyStruct = ViaReadonlyStruct();
Console.WriteLine($"{readonlyStruct.First}, {readonlyStruct.Second}");

Простой класс

Классы (Руководство по программированию на C#)

A type that is defined as a class is a reference type. At run time, when you declare a variable of a reference type, the variable contains the value null until you explicitly create an instance of the class by using the new operator, or assign it an object of a compatible type that may have been created elsewhere

public class SomeClass
{
   public int First { get; set; }
   public int Second { get; set; }
   public SomeClass(int first, int second)
   {
      First = first;
      Second = second;
   }
}

...

public SomeClass ViaSomeClass()
{
   return new SomeClass(1, 2);
}

...


var someClass = ViaSomeClass();
Console.WriteLine($"{someClass.First}, {someClass.Second}");

Выходные параметры

модификатор параметра out (справочник по C#)

The out keyword causes arguments to be passed by reference. It makes the formal parameter an alias for the argument, which must be a variable. In other words, any operation on the parameter is made on the argument. It is like the ref keyword, except that ref requires that the variable be initialized before it is passed. It is also like the in keyword, except that in does not allow the called method to modify the argument value. To use an out parameter, both the method definition and the calling method must explicitly use the out keyword.

public bool ViaOutParams(out int first, out int second)
{
   first = 1;
   second = 2;
   return someCondition;
}

...

if (ViaOutParams(out var firstInt, out var secondInt))
   Console.WriteLine($"{firstInt}, {secondInt}");

Исходящий кортеж значений

public bool ViaOutTuple(out (int first,int second) output)
{
   output = (1, 2);
   return someCondition;
}

...

if (ViaOutTuple(out var output))
   Console.WriteLine($"{output.first}, {output.second}");

Примечание. Доступно в C# 7.0+.

Adrian 08.04.2019 10:50

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

Petter Pettersson 11.04.2019 11:57

Создайте массив int. Или другой способ - создать класс.

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

Marc Gravell 08.04.2019 10:51

Это неплохо, но в текущем вопросе это не нужно.

Vuk Uskokovic 08.04.2019 10:52

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

Jonesopolis 08.04.2019 10:52

Вы тоже можете составить список.

Vuk Uskokovic 08.04.2019 10:54

@VukUskokovic, у которого (список) есть все проблемы, которые есть у массивов, плюс дополнительный объект и уровень абстракции; создание списка просто усугубляет проблема, если только мы не являемся семантически возвращение списка чего-либо

Marc Gravell 08.04.2019 10:54

Мой плохой, это неплохой способ, я думаю, что есть более простые способы.

Vuk Uskokovic 08.04.2019 10:55

@MarcGravell, я согласен, но вы можете составить список того, сколько целых чисел он хочет, чтобы он не возвращал только 2, вот как я получил вопрос.

Vuk Uskokovic 08.04.2019 10:58

@VukUskokovic достаточно честно - вопрос неясен и неоднозначен; если намерение по сути является произвольным методом List<double> GetHeights(), то да: это будет решение хорошо (оно показывает, насколько важен четкий контекст, который является проблемой вопроса, а не вашего ответа)

Marc Gravell 08.04.2019 10:59

@VukUskokovic Я добавил комментарий/запрос к вопросу

Marc Gravell 08.04.2019 11:01

@MarcGravell, спасибо.

Vuk Uskokovic 08.04.2019 11:02

Несколько способов:

  1. out параметры:

    private double GetHeight(out int anotherValue)
    {
        anotherValue = 42;
        return 2;
    }
    
  2. значения-кортежи:

    private (double height, int anotherValue) GetHeight()
    {
        return (42, 2);
    }
    

    (предупреждение: кортежи значений имеют известные проблемы при использовании в библиотеках .NET Standard, поскольку привязки сборок из .NET Standard в .NET Framework ... своего рода фубар)

  3. настраиваемые типы возврата:

    private Something GetHeight()
    {
        return new Something(42, 2);
    }
    

    (чтобы избежать распределения, вы можете определить Something как readonly struct в этом сценарии)

Также вы можете использовать параметры out:

static void Main(string[] args)
{
  int i, j;
  GetHeight(out i, out j);
}

public static void GetHeight(out int i1, out int i2)
{
  i1 = 1;
  i2 = 2;
}

Да, вы можете использовать Кортеж:

class Program
  {
    static void Main(string[] args)
    {
      Tuple<int, int> height = GetHeight();

      Console.WriteLine(height.Item1 + " - " + height.Item2);
      Console.ReadLine();
    }

    private static Tuple<int, int> GetHeight()
    {
      return new Tuple<int, int>(2, 3);
    }
  }

ВЫХОД:

2 - 3

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