2009-09-14 8 views
14

Posso assegnare ciascun valore in una matrice per separare le variabili in una riga in C#? Ecco un esempio di codice Ruby di ciò che voglio:C# assegna i valori dell'array alle variabili separate in una riga

irb(main):001:0> str1, str2 = ["hey", "now"] 
=> ["hey", "now"] 
irb(main):002:0> str1 
=> "hey" 
irb(main):003:0> str2 
=> "now" 

Non sono sicuro se quello che sto volendo è possibile in C#.

Modifica: per quelli che suggerisco di assegnare le stringhe "hey" e "now" alle variabili, non è quello che voglio. Immaginate la seguente:

irb(main):004:0> val1, val2 = get_two_values() 
=> ["hey", "now"] 
irb(main):005:0> val1 
=> "hey" 
irb(main):006:0> val2 
=> "now" 

Ora, il fatto che il metodo get_two_values restituito stringhe "hey" e "ora" è arbitraria. In effetti potrebbe restituire due valori qualsiasi, non devono nemmeno essere stringhe.

+3

Wow, brutto e confuso. Mi ricorda il mio ultimo appuntamento. – Will

+1

@Will: Davvero? Penso che sia bello e succinto, pur rimanendo chiaro e leggibile. Mi piace la funzionalità di Python e la uso frequentemente. – Randolpho

+1

Da una prospettiva C#, sicuramente. Sembra che tu stia assegnando un riferimento a un singolo array a due diversi tipi di varaibles ... come str1 = new string [] {"one", "two"}; str2 = str1; Quindi è immediatamente confuso con gli sviluppatori di C#. Il brutto pezzo era solo per adattarmi allo scherzo. – Will

risposta

12

Questo non è possibile in C#.

La cosa più vicina che posso pensare è quello di utilizzare l'inizializzazione nella stessa linea con indexs

strArr = new string[]{"foo","bar"}; 
string str1 = strArr[0], str2 = strArr[1]; 
+1

Questo è essenzialmente ciò che fa il rubino sotto le coperte; la cosa che @Sarah vuole fare è fondamentalmente zucchero sintattico. – Randolpho

+0

Lo chiamerei sintattico s-qualcosa. Ruby nasconde le differenze tra l'allocazione di memoria dei primitivi e dei tipi di riferimento ??? – Will

+1

Ruby è un linguaggio di scripting. Non ci sono tipi primitivi; sono tutti sullo heap - tipi di riferimento. – Randolpho

1

Lo si può fare in una sola riga, ma non come una dichiarazione.

Ad esempio:

int str1 = "hey"; int str2 = "now"; 

Python e Ruby sostenere l'assegnazione si sta cercando di fare; C# no.

2

Non sono sicuro se quello che sto volendo è possibile in C#.

Non lo è.

0

No, ma è possibile inizializzare un array di stringhe:

string[] strings = new string[] {"hey", "now"}; 

Anche se questo non è probabilmente troppo utile per voi. Francamente non è difficile metterli su due linee:

string str1 = "hey"; 
string str2 = "now"; 
4

Il caso d'uso nel mondo reale per questo sta fornendo un modo conveniente per restituire più valori da una funzione. Quindi è una funzione Ruby che restituisce un numero fisso di valori nella matrice e il chiamante li vuole in due variabili separate. Questo è dove la caratteristica più senso:

first_name, last_name = get_info() // always returns an array of length 2 

Per esprimere questo in C# si dovrebbe segnare i due parametri con out nella definizione del metodo, e restituire void:

public static void GetInfo(out string firstName, out string lastName) 
{ 
    // assign to firstName and lastName, instead of trying to return them. 
} 

E così chiamarla :

Non è così bello. Speriamo che alcuni futura versione di C# consentirà a questa:

var firstName, lastName = SomeClass.GetInfo(); 

Per abilitare questa, il metodo GetInfo restituirebbe una Tuple<string, string>.Ciò rappresenterebbe una modifica ininterrotta della lingua poiché gli attuali usi legali di var sono molto restrittivi, quindi non esiste ancora un uso valido per la sintassi "dichiarazione multipla" di cui sopra.

2

si può fare questo in C#

string str1 = "hey", str2 = "now"; 

o si può essere di fantasia come questo

 int x, y; 
     int[] arr = new int[] { x = 1, y = 2 }; 
6

Aggiornamento: In C# 7 si può facilmente assegnare più variabili contemporaneamente utilizzando tuple. Al fine di assegnare gli elementi dell'array alle variabili, avresti bisogno di scrivere un adeguato metodi Deconstruct() di estensione:

Un altro modo per consumare tuple è quello di decostruire loro. Una decostruzione dichiarazione è una sintassi per la divisione di una tupla (o altro valore) in sue parti e l'assegnazione di quelle parti singolarmente alle variabili fresche:

(string first, string middle, string last) = LookupName(id1); // deconstructing declaration 
WriteLine($"found {first} {last}."); 

In una dichiarazione Deconstructing è possibile utilizzare var per i singoli variabili dichiarate :

(var first, var middle, var last) = LookupName(id1); // var inside 

O anche mettere un singolo var al di fuori delle parentesi come abbreviazione:

var (first, middle, last) = LookupName(id1); // var outside 

È possibile anche decostruisci in variabili esistenti con una decostruzione assegnazione:

(first, middle, last) = LookupName(id2); // deconstructing assignment 

decostruzione non è solo per le tuple. Qualsiasi tipo può essere destrutturata, fintanto che ha un (istanza o estensione) Metodo deconstructor del forma:

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... } 

I parametri out costituiscono i valori risultanti dal decostruzione.

(Perché utilizza i parametri anziché restituire una tupla? Questo è in modo da poter avere sovraccarichi multipli per diversi numeri di valori ).

class Point 
{ 
    public int X { get; } 
    public int Y { get; } 

    public Point(int x, int y) { X = x; Y = y; } 
    public void Deconstruct(out int x, out int y) { x = X; y = Y; } 
} 

(var myX, var myY) = GetPoint(); // calls Deconstruct(out myX, out myY); 

Sarà un modello comune per avere costruttori e deconstructors essere “simmetrica” in questo modo. https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/


Vecchia risposta:

In realtà, è possibile ottenere una funzionalità simile in C# utilizzando metodi di estensione come questo (nota: non ho includere controllando se gli argomenti sono validi) :

public static void Match<T>(this IList<T> collection, Action<T,T> block) 
{ 
    block(collection[0], collection[1]); 
} 
public static void Match<T>(this IList<T> collection, Action<T,T,T> block) 
{ 
    block(collection[0], collection[1], collection[2]); 
} 
//... 

E li si può usare in questo modo:

012.
new[] { "hey", "now" }.Match((str1, str2) => 
{ 
    Console.WriteLine(str1); 
    Console.WriteLine(str2); 
}); 

Nel caso sia necessario un valore restituito da una funzione, il seguente overload funzionerebbe:

public static R Match<T,R>(this IList<T> collection, Func<T, T, R> block) 
{ 
    return block(collection[0], collection[1]); 
} 

private string NewMethod1() 
{ 
    return new[] { "hey", "now" }.Match((str1, str2) => 
    { 
     return str1 + str2; 
    }); 
} 

In questo modo:

  • si evita di dover ripetere il nome di matrice come in soluzione proposto da JaredPar e altri; la lista delle "variabili" è facile da leggere.

  • Si evita di dover dichiarare esplicitamente tipi di variabili come nella soluzione di Daniel Earwicker.

Lo svantaggio è che si finisce con un ulteriore blocco di codice, ma penso che ne valga la pena. È possibile utilizzare frammenti di codice per evitare di digitare manualmente parentesi, ecc.

So che è una domanda di 7 anni, ma non tanto tempo fa avevo bisogno di una soluzione del genere - dare facilmente nomi agli elementi di array passati nel metodo (no, usare classi/structs invece di array non era pratico, perché per le matrici stesse potevo bisogno di diversi nomi di elementi in modi diversi) e, purtroppo, ho finito con codice come questo:

var A = points[0]; 
var A2 = points[1]; 
var B = points[2]; 
var C2 = points[3]; 
var C = points[4]; 

ora potrei scrivere (in realtà, ho refactoring uno di questi metodi in questo momento!):

points.Match((A, A2, B, C2, C) => {...}); 

La mia soluzione è simile a pattern matching in F # e mi è stato ispirato da questa risposta: https://stackoverflow.com/a/2321922/6659843

0

È possibile utilizzare il nome tuple con C# 7 ora.

{ 
    (string part1, string part2) = Deconstruct(new string[]{"hey","now"}); 
} 

public (string, string) Deconstruct(string[] parts) 
{ 
    return (parts[0], parts[1]); 
}