Поддерживает ли С# несколько возвращаемых значений?

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

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

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

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 ();
}

Вопрос: я закрыл?

Ответы

Ответ 1

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

В общем, однако, у вас есть следующие опции:

Использование параметров 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 }
}    

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

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

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

С# 7.0 Кортежи

С# 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}.");

Ответ 2

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

Ответ 3

С# не поддерживает идею прямого возвращения нескольких значений из метода таким образом. Однако существует несколько способов создания методов, которые возвращают несколько значений. Во-первых, используйте параметры 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);
}

Ответ 4

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

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

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

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

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

Ответ 5

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

Ответ 6

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

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

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

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

mc.GetHour(1, 2);

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

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

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

Ответ 7

Извините, вы не можете этого сделать. Вам лучше будет возвращать массив или объект. Вы можете вернуть объект 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 ();
            }

Ответ 8

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

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

Ответ 9

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

return x, y

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

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


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

public static void xxx (ref var1, ref var2, ref var3) {      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());

Ответ 10

В С# метод может возвращаться несколько раз, если вы используете формат 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"

Ответ 11

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

Итак, коротко. Зачем? Инкапсулировать возвращаемые значения в ОДНОМ объекте? Не выполняйте несколько действий в одной функции.

РЕДАКТИРОВАТЬ: В вашем случае я бы даже не включил вашу функциональность только в функцию:

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

        Console.ReadLine ();
        }

И ваше имя функции GetHour не выполняет то, что говорит функция... если он говорит GetHour, он должен вернуть час и не час плюс минута.