Поддерживает ли C # несколько возвращаемых значений? - PullRequest
13 голосов
/ 22 октября 2010

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

Работа с классами, методами и возвращаемыми значениями.

Я бы хотел, чтобы мой класс / метод возвращали Текущий час и Минуту. Достаточно просто, правда. Это правильно или правильно построено?

class MyClass
{
    public int GetHour (int hr, int min)
    {
        DateTime dt = DateTime.Now;
        int hour = dt.Hour;
        int minute = dt.Minute;

        return hour;
        return minute;

    }
}

И, вызывая его из Main(): Получение некоторых ошибок (No overload for method и Unreachable code detected)

static void Main ( string[] args )
{
    MyClass mc = new MyClass ();
    Console.WriteLine ("Hour: {0} \n Minute: {1}", mc.GetHour());   
    Console.ReadLine ();
}

Вопрос: я рядом?

Ответы [ 11 ]

30 голосов
/ 22 октября 2010

Как упомянуто @ChaosPandion, в этом конкретном случае вы должны вернуть DateTime struct.

Как правило, у вас есть следующие опции:

Использование out параметров

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

public void GetTime(out int hr, out int min) 
{ 
    DateTime dt = DateTime.Now;
    hr = dt.Hour;
    min = dt.Minute;
}

static void Main(string[] args)
{
     // declare variables for out parameters first
     int hour, minute;
     GetTime(out hour, out minute);
}

Использование массива

Это простой метод, который хорошо работает, если возвращаемые значения имеют одинаковый тип.

public int[] GetTime() 
{ 
    DateTime dt = DateTime.Now;
    return new[] { dt.Hour, dt.Minute};
}

Использование пакета свойств (Пакет свойств - это простой класс, обладающий только свойствами)

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

class A
{ 
     int Prop1 { get; set; }
     int Prop2 { get; set; }
}

public A SomeMethod()
{
    return new A() { Prop1 = 1, Prop2 = 2 }
}    

Использование кортежа

В C # 4.0 (требуется VS 2010) вы можете использовать Tuple<T1, T2, ...> класс:

public Tuple<int, int> GetTime() 
{ 
    DateTime dt = DateTime.Now;
    return Tuple.Create(dt.Hour, dt.Minute);
}

C # 7.0 Кортежи

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

(string, string, string) LookupName(long id) // tuple return type
{
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
}

Элементами кортежа являются имена Item1, Item2 и т. Д. По умолчанию, но вы также можете указать имена, например,

(string first, string middle, string last) LookupName(long id) // tuple return type
{
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
}

и затем получить доступ к элементам кортежа через эти имена:

var names = LookupName(id);
WriteLine($"found {names.first} {names.last}.");
6 голосов
/ 22 октября 2010

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

3 голосов
/ 22 октября 2010

C # не поддерживает идею прямого возврата нескольких значений из метода таким способом. Однако есть несколько способов создать методы, которые возвращают несколько значений. Первый - использовать параметры ref / out.

public void GetHourMinute(out int hour, out int minute) { 
  var now = DateTime.Now;
  hour = now.Hour;
  minute = now.Minute;
}

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

public Tuple<int,int> GetHourMinute() {
  var now = DateTime.Now;
  return Tuple.Create(now.Hour, now.Minute);
}
2 голосов
/ 22 октября 2010

Я предлагаю вам вернуть объект DateTime. Затем в вашем основном методе вы вызываете свойства Hour и Minute.

2 голосов
/ 22 октября 2010

1: у вас не может быть двух return с. Как только компилятор достигает оператора return, операция метода завершается.
2: Почему вы хотите, чтобы ваш метод получал параметры, если вы их не используете? DateTime.Now дает вам текущее время, , если вы будете думать о себе как об этом методе - что вам нужно для выполнения вашей задачи? Ничего.

Итак, практические советы:
1. На самом деле DateTime делает то, что вам нужно лучше, чем ваш метод.

Console.WriteLine ("Hour: {0} \n Minute: {1}", DateTime.Now.Hour,DateTime.Now.Minute);

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

2 Возвращение двух значений противоречит концепции метода - метод возвращает одну вещь (существуют исключения как out ref, но мы их игнорируем).
Вы можете увидеть это в своем собственном коде - имя вашего метода GetHour не GetHourAndMinutes. Я не думаю, что когда-либо видел имя метода со словом «и» - метод делает только одно.

1 голос
/ 22 октября 2010

В C # метод может возвращаться несколько раз, если вы используете yield return формат.

using System.Collections.Generic;

namespace YieldReturn
{
    class Program
    {
        public static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            IEnumerator<int> enu = mc.GetHour().GetEnumerator();
            enu.MoveNext();
            int hour = enu.Current;
            enu.MoveNext();
            int min = enu.Current;
            Console.WriteLine("Hour {0} min {1}", hour, min);
            Console.ReadKey(true);
        }
    }

    class MyClass
    {
        DateTime dt;

        public MyClass()
        {
            dt = DateTime.Now;
        }
        public IEnumerable<int> GetHour()
        {
            int hour = dt.Hour;
            int minute = dt.Minute;
            yield return hour;
            yield return minute;
        }
    }
}

Дает "Час 8 мин 50"

1 голос
/ 22 октября 2010

Вы не можете вернуться дважды, только один раз.
Несколько возвращаемых значений одновременно требуют лямбда-выражений, и AFAIK, только Python способен на это.
Синтаксис выглядит так:

return x, y

Так что, возможно, вам стоит попробовать IronPython, а затем декомпилировать в C #.

В C # есть ровно два способа вернуть более одного значения:
1. Используйте аргументы как вызов по ссылке, таким образом, вы можете назначить 3 переменные и затем вернуть.
2. Используйте какой-нибудь struct / class / array / tuple / vector и поместите в него несколько значений.

Вызов по ссылке выглядит примерно так:

публичная статическая пустота ххх (ref var1, ref вар2, исх вар3) { var1 = 123; var2 = 456; var3 = 789; вернуть; }

тогда вы делаете:

int a =1;
int b=2;
int c=3;

xxx(ref a, ref b, ref c);

Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
Console.WriteLine(c.ToString());
1 голос
/ 22 октября 2010

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

Если подумать, для того, что вам нужно выше, вам даже не нужно писать описанный выше метод. Просто используйте DateTime.Now.TimeOfDay прямо в вашем коде

1 голос
/ 22 октября 2010

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

Также, как уже говорилось, подпись вашей функции вызывалась неправильно.

class MyClass
        {
        public int[] GetHour ()
            {
            DateTime dt = DateTime.Now;

            int hour = dt.Hour;
            int minute = dt.Minute;

            return new int[]{hour, minute};
            }
        }

static void Main ( string[] args )
            {
            MyClass mc = new MyClass ();
int[] temp = mc.GetHour();
            Console.WriteLine ("Hour: {0} \n Minute: {1}", temp[0], temp[1]);

            Console.ReadLine ();
            }
1 голос
/ 22 октября 2010

Да, вы можете вернуть только одну «вещь» из метода в C #.

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

public int GetHour (int hr, int min) // here
{
}

являются параметрами. И вам нужно указать их при вызове метода, например так:

mc.GetHour(1, 2);

Но, конечно, в вашем случае это не имеет смысла.

Чтобы ответить на общий вопрос: «Как мне вернуть более одной вещи?» Вы инкапсулируете его в класс, устанавливаете свойства и возвращаете этот класс. Так получилось, что в приведенном вами примере класс DateTime делает именно это.

Надеюсь, это полезно.

...