2010-10-21 14 views
13

Questa è una domanda molto semplice, e se quello che sto pensando di fare è complicato/coinvolto, allora non mi aspetto che tu vada nei dettagli ... Ho letto che questo può coinvolgere le strutture o l'hash o qualche altro procedura spaventosa che non ho ancora ottenuto. Se è così, sono sicuro che mi farò presto.Il C# supporta più valori di ritorno?

Utilizzo di classi di apprendimento, metodi e valori restituiti.

Mi piacerebbe avere la mia classe/metodo restituire ora corrente e minuti. Abbastanza semplice, davvero. È costruito correttamente o correttamente?

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; 

    } 
} 

E, chiamandolo da Main(): Come alcuni errori (No overload for method e Unreachable code detected)

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

domanda è: Am I Chiudere?

+1

risposta breve: NO, è possibile restituire più valori in array, elenco, dizionario o qualsiasi raccolta –

+0

Perché non si memorizza 'DateTime.Now' su' mc' e si utilizzano le sue proprietà? – BrunoLM

+0

possibile duplicato di [Come posso restituire più valori da una funzione in C#?] (Http://stackoverflow.com/questions/748062/how-can-i-return-multiple-values-from-a-function-in -c) – nawfal

risposta

6

C# non supporta più valori di ritorno, quindi in questo caso è necessario restituire una struttura DateTime che rappresenta l'approccio idiomatico. Il codice cliente può semplicemente ignorare le proprietà di cui non si preoccupano. È possibile creare la propria struttura semplice, ma in realtà non ne vale la pena.

+0

Il mio primo pensiero a questo è stato quello di creare un nuovo metodo, chiamato GetMinute che assomiglierebbe molto a GetHour ... ma l'uomo sarebbe un sacco di codice per una cosa facile. Non so ancora delle strutture. Grazie! – DonG

+2

@DonG - Il più grande vantaggio dell'uso di 'DateTime' è la chiarezza. Quasi tutti gli sviluppatori .NET sapranno esattamente come utilizzare il tuo codice. – ChaosPandion

1

Sì, puoi solo restituire una "cosa" dal metodo in C#.

L'altro problema è che si chiama un metodo senza parametri. Le cose tra parentesi:

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

Sono parametri. E è necessario specificare quando si chiama il metodo, in questo modo:

mc.GetHour(1, 2); 

Ma, naturalmente, nel tuo caso, non ha senso fare questo.

Per rispondere alla domanda generale di: "Come restituisco più di una cosa?" Lo si incapsula in una classe, si impostano le proprietà e si restituisce quella classe. Succede, nell'esempio che hai dato, la classe DateTime fa proprio questo.

Spero che questo sia utile.

1

Siamo spiacenti, non è possibile farlo. Sarebbe meglio servire restituendo un array o un oggetto. È possibile restituire l'oggetto DateTime e usarlo.

Inoltre, come indicato, la firma della funzione non è stata chiamata correttamente.

+0

Oh, so che sto facendo un sacco di cose improprie! :-) Grazie! – DonG

3

C# non supporta l'idea di restituire direttamente più valori da un metodo in quel modo. Tuttavia ci sono un paio di modi per creare metodi che restituiscono più valori. Il primo è utilizzare i parametri ref/out.

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

Il secondo è quello di creare un tipo di wrapper che incapsula i due valori. A partire da 4.0 questo può essere reso un po 'più semplice usando il tipo Tuple.

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

Senza il supporto per la tupla di prima classe, generalmente tengo queste cose private. – ChaosPandion

+0

Ok, brucerò, voglio dire attraversare quel ponte quando ci arrivo. Questa è stata la mia piccola esplorazione sui valori di ritorno. Grazie! – DonG

+0

@DonG, per quanto riguarda il suggerimento di utilizzare i parametri 'out', vi rimando a http://stackoverflow.com/questions/2366741/what-is-bad-practice-when-using-out-parameters – DaveDev

2

1: Non è possibile avere due return s.Una volta che il compilatore raggiunge l'istruzione return, l'operazione del metodo è terminata.
2: Perché vuoi che il tuo metodo riceva i parametri se non li usi? DateTime.Now ti dà l'ora corrente, se pensi a te stesso come quel metodo - cosa ti serve per completare il tuo compito? Niente.

Quindi, consigli pratici:
1. In realtà, DateTime fa ciò che ti serve meglio del tuo metodo.

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

sarebbe stato meglio,
ma cerchiamo di ignorare che e lo considerano un esercizio di classi.

2 Il ritorno di due valori è contrario al concetto di un metodo: un metodo restituisce una cosa (esistono eccezioni come outref, ma li ignoreremo).
Si può effettivamente vedere che nel proprio codice - il nome del metodo è GetHour non GetHourAndMinutes. Non penso di aver mai visto il nome di un metodo con la parola "e" - un metodo fa solo una cosa.

2

Suggerisco di restituire l'oggetto DateTime. Quindi nel tuo metodo principale chiami le proprietà Hour e Minute.

1

Non è possibile restituire più valori. TimeSpan è esattamente quello che stai cercando. Crea un oggetto con ore, minuti e secondi che vuoi catturare e restituirlo.

Vieni a pensarci, per quello che ti serve sopra, non devi nemmeno scrivere il metodo sopra. Basta usare DateTime.Now.TimeOfDay direttamente nel tuo codice

+0

Sì, questa è un'idea migliore per usare semplicemente TimeOfDay, ma il mio esperimento qui era di giocare con la restituzione di più valori. Sono nella settimana 3 della classe C# ... Grazie! – DonG

29

Come menzionato da @ChaosPandion, in quel caso specifico restituiresti una struttura DateTime.

In generale, tuttavia, si avrebbe le seguenti opzioni:

Utilizzando out parametri

Questo è un modo semplice che di solito funziona sempre. Tuttavia, è un po 'goffo, in quanto il risultato viene restituito dove normalmente ci si aspetterebbe che gli argomenti della funzione vengano passati e che la firma del metodo possa essere lunga e difficile da ridefinire.

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

Utilizzando una matrice

Questo è un metodo semplice che funziona bene se i valori del reso hanno lo stesso tipo.

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

Utilizzando un elenco di proprietà (Un sacchetto struttura è una semplice classe che ha solo proprietà)

Questo è molto comodo e consente una facile modifica del tipo e del numero di valori restituiti in seguito senza cambiare la firma del metodo.

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

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

Utilizzando una tupla

In C# 4.0 (richiede VS 2010) è possibile utilizzare la classe Tuple<T1, T2, ...>:

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

C# 7.0 tuple

C# 7.0 aggiunge supporto per più valori di ritorno. È possibile scrivere codice come questo per restituire una tupla implicitamente creato:

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

Gli elementi tuple sono nomi Item1, Item2, ecc per impostazione predefinita, ma è anche possibile specificare i nomi, per esempio

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

e poi accedere agli elementi tuple via quei nomi:

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

Trovo i parametri un po 'goffi ma questa è sicuramente una soluzione praticabile. – ChaosPandion

+1

@ChaosPandion: Sì, ci sono sicuramente approcci migliori, sto solo cercando di dare una panoramica delle possibilità. –

+0

Correggi l'ortografia: Tupel dovrebbe essere Tupla. – mtreit

1

Non è possibile tornare due volte, una sola volta.
Diversi valori restituiti in una volta richiedono espressioni lambda e AFAIK, solo Python è in grado di farlo.
Sintassi non va in questo modo:

return x, y 

Così forse si dovrebbe cercare IronPython, e poi decompilare a C#.

In C#, ci sono esattamente due modi per restituire più di un valore:
1. Usare argomenti di chiamata di riferimento, in questo modo è possibile assegnare 3 variabili e poi tornare.
2. Usa qualche tipo di struct/class/array/tuple/vector e metti i tuoi valori multipli in esso.

chiamata per riferimento è qualcosa di simile:

public void xxx statico (var1 ref, ref var2, var3 ref) { var1 = 123; var2 = 456; var3 = 789; ritorno; }

poi si fa:

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

In C# un metodo può restituire più volte, se si utilizza il formato 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; 
     } 
    } 
} 

dà "ore 8 min 50"

0

La domanda che vorrei chiederti è perché vuoi tornare più valori? Restituire più valori per me significa avere più responsabilità nella funzione e questo dovrebbe essere un grosso problema, dal momento che sta violando lo SRP. Ma se quei valori di ritorno sono correlati forse creano un oggetto che ti manca e dovresti invece crearlo? O una lista con un tipo di oggetto.

Quindi per brevità. Perché? Incapsula i tuoi valori di ritorno in UN oggetto?Non fare più cose in una funzione.

EDIT: Nel tuo caso non avrei nemmeno avvolgere la funzionalità in una funzione basta scrivere:

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

E il tuo nome della funzione GetHour non fa quello che dice la funzione ... se dice GetHour dovrebbe restituire l'ora e non l'ora più il minuto.

Problemi correlati