2009-04-14 9 views
8

Diciamo per un momento che C# ha permesso più valori di ritorno nel senso più puro, dove ci si aspetterebbe di vedere qualcosa di simile:C# - Zuccheri sintattici per parametri esterni?

string sender = message.GetSender(); 
string receiver = message.GetReceiver(); 

compattato a:

string sender, receiver = message.GetParticipants(); 

In tal caso, Non devo capire i valori di ritorno del metodo finché non faccio effettivamente la chiamata al metodo. Forse mi affido ad Intellisense per dirmi quale valore/i di rendimento ho a che fare, o forse sto cercando un metodo che restituisca ciò che voglio da una classe con cui non ho familiarità.

Allo stesso modo, abbiamo qualcosa di simile, attualmente, in C#:

string receiver; 
string sender = message.GetParticipants(out receiver); 

dove l'argomento per GetParticipants è un parametro fuori stringa. Tuttavia, questo è un po 'diverso da quello sopra perché significa che devo anticipare, o almeno tornare indietro e scrivere, codice che crea una variabile per contenere il risultato del parametro out. Questo è un po 'controintuitivo.

La mia domanda è, c'è qualche zucchero sintattico nell'attuale C#, che consente a uno sviluppatore di fare questa dichiarazione nella stessa riga della chiamata al metodo? Penso che sarebbe rendere lo sviluppo di una (piccola) po 'più fluida, e anche rendere il codice più leggibile se stessi facendo qualcosa di simile:

string sender = message.GetParicipants(out string receiver); 

per dimostrare che il ricevitore veniva dichiarato e assegnato sul posto.

+0

L'esempio C# esistente deve aggiungere il modificatore "out" all'argomento * pure: string sender = message.GetParticipants (out receiver); –

+0

modifica GetParicipants, non ho i diritti per farlo –

+0

Questo è stato [suggerito come possibile funzionalità per C# 6.0] (http://damieng.com/blog/2013/12/09/probable-c-6- 0-caratteristiche-illustrate). –

risposta

9

No, attualmente non esiste uno zucchero sintattico intorno a questo. Non ho sentito alcuna intenzione di introdurre nessuno dei due.

Non posso dire di usare i parametri out abbastanza spesso perché sia ​​davvero una preoccupazione significativa per me (ci sono altre funzionalità che preferirei che il team C# passasse il loro tempo) ma sono d'accordo che è un po 'fastidioso.

+0

In che modo l'implementazione corrente è un doppio standard ...? –

+0

Poiché non sono valori di ritorno, sono fuori parametri. Non esiste un "doppio standard": sono cose diverse, trattate in modo diverso. Non è che tu rappresenti il ​​valore di ritorno come un parametro iniziale o qualcosa del genere - a * quel punto * sarebbe giusto definirlo un doppio standard. –

+0

Nota che i parametri out * non sono * uguali ai valori di ritorno. È possibile assegnare il valore di un parametro out durante il metodo e tale modifica avviene immediatamente. Puoi vedere questo se chiami un metodo e usi una variabile di istanza per l'argomento out. –

0

Nella migliore delle ipotesi, è necessario utilizzare var anziché un tipo esplicito, a meno che non si desideri limitare tutti i valori di restituzione multipli dello stesso tipo (probabilmente non pratico). Dovresti anche limitare l'ambito della variabile; attualmente è possibile dichiarare una variabile con uno scope più elevato e inizializzarla in un parametro out. Con questo approccio, la variabile andrebbe fuori ambito nello stesso blocco della sua assegnazione. Ovviamente questo è utilizzabile in alcuni casi, ma non vorrei imporlo come regola generale. Ovviamente è possibile lasciare l'opzione 'out' in posizione, ma è probabile che le persone eseguano il codice per un approccio o l'altro.

+0

Dovendo usare var non è vero, lo zucchero sintattico, se esistesse, dovrebbe semplicemente dichiarare una nuova variabile nello stesso ambito menzionato e passarla nel metodo per l'assegnazione. Pertanto, ogni parametro dovrebbe essere digitato naturalmente. – JoshJordan

+0

string param1, int param2 = FuncCall (param3)? –

+0

Il post chiedeva dello zucchero sintattico del modulo: stringa restituita = FuncCall (out int param2, out stringa param3). Tuttavia, ciò che hai pubblicato sarebbe una forma valida, sì. – JoshJordan

-1

provare il seguente codice

Participants p = message.GetParticipants(); 
log(p.sender,p.receiver); 
-1

credo che questo non è ciò che si desidera. Potrebbe esserti imbattuto in un pezzo di codice in cui ti piacerebbe che fosse . Ma le variabili che appaiono dal nulla, perché sono stati introdotti nella lista dei parametri sarebbero un incubo personale (per me :))

valori di ritorno multipli hanno gravi svantaggi dal punto di portabilità/manutenibilità. Se si esegue una funzione che restituisce due stringhe e ora si desidera restituire tre, sarà necessario modificare tutto il codice che utilizza questa funzione. Un tipo di record restituito tuttavia di solito è piacevole in tali scenari comuni.

voi potrebbero aprire il vaso di pandora ;-)

Per la linea compattazione:

string s1, s2; s1 = foo.bar(s2); 

Le linee possono essere qualsiasi lunghezza, così da poter confezionare alcune cose comuni in uno solo. Prova solo a convivere con il punto e virgola.

+1

Si prega di non compattarlo ... – Jabe

+0

Beh, ci sono molti, molti costrutti che hanno già implicazioni severe per la manutenibilità, e gli sviluppatori devono imparare a lavorare con loro. In questo caso, è più probabile che non sia appropriato introdurre un altro metodo con lo stesso nome ma con una diversa firma di ritorno. – JoshJordan

+0

Il punto è che le variabili "che escono dal nulla" sono ciò che abbiamo per un singolo valore di ritorno, se scegliamo di fare una dichiarazione e un incarico. La mancanza di una funzione per fare questo per valori di ritorno multipli (o parametri out) ci dà un doppio standard. – JoshJordan

5

.NET 4 aggiungerà un concetto Tuple, che si occupa di questo. Sfortunatamente, il linguaggio C# non fornirà alcun supporto linguistico per "destructuring bind".

+2

Si chiama "binding destructuring". –

2

È inoltre possibile restituire un Tuple<T,U> o qualcosa di simile. Tuttavia, dal momento che si desidera restituire due stringhe, potrebbe creare confusione.

Io uso le strutture Tuples di BclExtras library che è molto utile (trovato su SO, grazie JaredPar!).

4

Personalmente, mi piace l'inconverenza introdotta quando si utilizzano i parametri. Mi aiuta a pensare se il mio metodo sta davvero facendo quello che dovrebbe essere o se ho inserito troppe funzionalità in esso. Detto questo, forse la digitazione dinamica in C# 4.0/.Net 4 risolverà alcuni dei tuoi dubbi.

dynamic participant = message.GetParticipants(); 

var sender = participant.Sender; 
var recipient = participant.Recipient; 

dove

public object GetParticipants() 
{ 
    return new { Sender = ..., Recipient = ... }; 
} 
+0

Yuck, sembra così brutto! –

2

Non credo esista tale funzionalità, ma se fosse attuata in modo simile agli array in Perl che potrebbero essere utili in realtà.

In perl È possibile assegnare un array a un elenco di variabili tra parentesi. Così si può per esempio fare questo

 
($user, $password) = split(/:/,$data); 
2

Dove questo mi bug più: poiché non c'è un sovraccarico di (diciamo) DateTime.TryParse che non prende un parametro out, non si può scrivere

if (DateTime.TryParse(s, out d)) 
{ 
    return new ValidationError("{0} isn't a valid date", s); 
} 

senza dichiarare d. Non so se questo è un problema con i parametri out o solo con il modo in cui il metodo TryParse è implementato, ma è fastidioso.