2010-10-21 24 views
13

Esta es una pregunta muy básica, y si lo que estoy pensando hacer es complicado/complicado, entonces no espero que entres en detalles ... He leído que esto puede implicar estructuras o hash o algún otro procedimiento de miedo que aún no he tenido. Si es así, estoy seguro de que me alcanzará pronto.¿C# admite múltiples valores devueltos?

Trabajando en el aprendizaje de clases, métodos y valores devueltos.

Me gustaría que mi clase/método devuelvan Hora y minutos actuales. Lo suficientemente simple, realmente. ¿Está construido correctamente o correctamente?

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; 

    } 
} 

Y, llamando desde Main(): Para hacer algo de errores (No overload for method y Unreachable code detected)

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

pregunta es: ¿Estoy cerca?

+1

respuesta corta: NO, puede devolver varios valores en una matriz, lista, diccionario o cualquier colección –

+0

¿Por qué no almacena 'DateTime.Now' en' mc' en su lugar y usa sus propiedades? – BrunoLM

+0

posible duplicado de [¿Cómo puedo devolver múltiples valores desde una función en C#?] (Http://stackoverflow.com/questions/748062/how-can-i-return-multiple-values-from-a-function-in -c) – nawfal

Respuesta

6

C# no es compatible con valores de retorno múltiples, por lo que en este caso debe devolver una estructura DateTime que es el enfoque idiomático. El código del cliente simplemente puede ignorar las propiedades que no les importan. Podrías crear tu propia estructura simple pero realmente no vale la pena el esfuerzo.

+0

Lo primero que pensé fue crear un nuevo método, llamado GetMinute, que se pareciera mucho a GetHour ... pero que sería una gran cantidad de código para una cosa fácil. Todavía no sé nada sobre las estructuras. ¡Gracias! – DonG

+2

@DonG: la mayor ventaja de utilizar 'DateTime' es la claridad. Casi todos los desarrolladores .NET sabrán exactamente cómo usar su código. – ChaosPandion

1

Sí, solo puede devolver una 'cosa' del método en C#.

El otro problema que tiene es que está llamando a un método sin ningún parámetro. Las cosas entre corchetes:

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

Son parámetros. Y es necesario especificar cuando una llamada al método, así:

mc.GetHour(1, 2); 

Pero, por supuesto, en su caso, no tiene sentido hacer esto.

Para responder a la pregunta general de: "¿Cómo devuelvo más de una cosa?" Lo encapsula en una clase, establece las propiedades y devuelve esa clase. Sucede que, en el ejemplo que has dado, la clase DateTime hace precisamente eso.

Espero que esto sea útil.

1

Lo sentimos, no puedes hacer eso. Sería mejor si devolvieras una matriz o un objeto. Puede devolver el objeto DateTime y usarlo.

También como se indicó, la firma de su función no se estaba llamando correctamente.

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

¡Oh, sé que estoy haciendo muchas cosas impropias! :-) ¡Gracias! – DonG

3

C# no es compatible con la idea de devolver directamente varios valores de un método de esa manera. Sin embargo, hay un par de maneras de crear métodos que devuelven valores múltiples. El primero es usar los parámetros ref/out.

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

El segundo es crear un tipo de envoltura que encapsula los dos valores. Comenzar en 4.0 esto se puede hacer un poco más fácil usando el tipo Tuple.

public Tuple<int,int> GetHourMinute() { 
    var now = DateTime.Now; 
    return Tuple.Create(now.Hour, now.Minute); 
} 
+1

Sin soporte de tupla de primera clase, generalmente mantengo esas cosas en privado. – ChaosPandion

+0

Está bien, me voy a quemar, me refiero a cruzar ese puente cuando lo encuentre. Esta fue mi pequeña exploración de los valores devueltos. ¡Gracias! – DonG

+0

@DonG, con respecto a la sugerencia de usar parámetros 'out', lo remito a http://stackoverflow.com/questions/2366741/what-is-bad-practice-when-using-out-parameters – DaveDev

2

1: No puede tener dos return s.Una vez que el compilador alcanza la instrucción return, la operación del método finaliza.
2: ¿Por qué le gustaría que su método reciba parámetros si no los usa? DateTime.Now le brinda la hora actual, , si piensa que es usted el único método, ¿qué necesita para completar su tarea? Nada.

Por lo tanto, consejos prácticos:
1. En realidad, DateTime hace lo que necesita mejor que su método.

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

hubiera sido mejor,
pero vamos a ignorar eso y lo consideran un ejercicio de clases.

2 La devolución de dos valores va en contra del concepto de un método: un método devuelve una cosa (existen excepciones como outref, pero las ignoraremos).
Puedes verlo en tu propio código: el nombre de tu método es GetHour, no GetHourAndMinutes. No creo haber visto nunca el nombre de un método con la palabra "y": un método solo hace una cosa.

2

Le sugiero que devuelva el objeto DateTime. Luego, en su método principal, llama a las propiedades de Hora y Minuto.

1

No puede devolver el valor múltiple. TimeSpan es exactamente lo que estás buscando. Cree un objeto de eso con hora, minuto e incluso segundo que quiera capturar y devolver.

Ahora que lo pienso, para lo que necesitas más arriba, ni siquiera tienes que escribir el método anterior. Solo use DateTime.Now.TimeOfDay directamente en su código

+0

Sí, esa es una mejor idea para usar TimeOfDay, pero mi experimento aquí fue jugar con devolver múltiples valores. Estoy en la semana 3 de la clase C# ... ¡Gracias! – DonG

29

Según lo mencionado por @ChaosPandion, en ese caso específico usted devolvería una estructura DateTime.

En general, sin embargo, que tendrían las siguientes opciones:

Usando out parámetros

Esta es una forma sencilla que por lo general siempre trabajar. Sin embargo, es un poco torpe, ya que el resultado se devuelve donde normalmente se espera que se pasen los argumentos de la función y la firma del método puede ser larga y difícil de refactorizar.

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

Usando un conjunto

Este es un método sencillo que funciona bien si los valores que ser devueltos tienen el mismo tipo.

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

Usando una bolsa de propiedades (A bolsa de propiedades es una clase simple que sólo tiene propiedades)

Esto es muy conveniente y permite una fácil modificación del tipo y número de valores devueltos más adelante sin cambiar la firma del método

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

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

Usando una tupla

En C# 4.0 (requiere VS 2010) se puede utilizar la clase Tuple<T1, T2, ...>:

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

C# 7.0 Tuplas

C# 7.0 añade soporte para múltiples valores de retorno. Se puede escribir código como este para devolver una tupla creado implícitamente:

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

Los elementos de tupla son nombres Item1, Item2, etc por defecto, pero también se puede especificar nombres, por ejemplo,

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

y luego acceder a los elementos de tupla a través de esos nombres:

var names = LookupName(id); 
WriteLine($"found {names.first} {names.last}."); 
+0

Me parece que los parámetros son un poco torpes, pero esta es sin duda una solución viable. – ChaosPandion

+1

@ ChaosPandion: Sí, ciertamente hay mejores enfoques, solo intento dar una visión general de las posibilidades. –

+0

Corrija la ortografía: Tupel debe ser Tuple. – mtreit

1

que no pueda regresar dos veces, una sola vez.
Varios valores devueltos a la vez requieren expresiones lambda, y AFAIK, solo Python es capaz de eso.
sintaxis no es así:

return x, y 

Así que tal vez debería intentar IronPython, y luego descompilar a C#.

En C#, hay exactamente dos formas de devolver más de un valor:
1. Use los argumentos como llamada por referencia, de esta forma puede asignar 3 variables y luego regresar.
2. Utilice algún tipo de struct/class/array/tuple/vector y coloque sus múltiples valores en él.

la llamada por referencia es algo como esto:

xxx public void estática (ref var1, var2 ref , var3 ref) { var1 = 123; var2 = 456; var3 = 789; devolución; }

entonces hacer:

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

En C# un método puede volver varias veces, si se utiliza yield return formato.

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

Da "horas 8 min 50"

0

La pregunta que me gustaría preguntarle por qué se desea devolver múltiples valores? Devolver múltiples valores para mí significa tener múltiples responsabilidades en la función y eso debería ser un gran problema, ya que infringe SRP. Pero, si esos valores de retorno están relacionados, ¿pueden crear un objeto que te falta y debería crearse en su lugar? O una lista con un tipo de objeto.

Así que para abreviar. ¿Por qué? Encapsule sus valores devueltos en UNO objetoNo hagas muchas cosas en una función.

EDIT: En su caso no podría siquiera envolver su funcionalidad en una función acaba de escribir:

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

Y el nombre de la función GetHour no hace lo que dice la función ... si dice GetHour debe devolver la hora y no la hora más el minuto.

Cuestiones relacionadas