Assegna valori di array a variabili separate in una riga
-
07-07-2019 - |
Domanda
Posso assegnare ciascun valore in un array a variabili separate in una riga in C#?Ecco un esempio nel codice Ruby di ciò che voglio:
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 che ciò che desidero sia possibile in C#.
Modificare: per coloro che suggeriscono di assegnare semplicemente le stringhe "hey" e "now" alle variabili, non è quello che voglio.Immagina quanto segue:
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
le stringhe restituite "hey" e "now" sono arbitrarie.In effetti potrebbe restituire due valori qualsiasi, non devono nemmeno essere stringhe.
Soluzione
Questo non è possibile in C #.
La cosa più vicina a cui riesco a pensare è usare l'inizializzazione nella stessa riga con gli indici
strArr = new string[]{"foo","bar"};
string str1 = strArr[0], str2 = strArr[1];
Altri suggerimenti
Aggiornamento: In C#7 puoi assegnare facilmente più variabili contemporaneamente utilizzando le tuple.Per assegnare elementi dell'array alle variabili, dovresti scrivere un file appropriato Deconstruct()
metodi di estensione:
Un altro modo per consumare le tuple è decostruirle.Una dichiarazione di decostruzione è una sintassi per dividere una tupla (o altro valore) nelle sue parti e assegnare tali parti singolarmente a nuove variabili:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration WriteLine($"found {first} {last}.");
In una dichiarazione di decostruzione è possibile utilizzare VAR per le singole 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
Puoi anche decostruire in variabili esistenti con un incarico di decostruzione:
(first, middle, last) = LookupName(id2); // deconstructing assignment
La decostruzione non riguarda solo le tuple.Qualsiasi tipo può essere decostruito, purché abbia un metodo di decostruttore (istanza o estensione) della forma:
public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }
I parametri OUT costituiscono i valori che derivano dalla decostruzione.
(Perché utilizza i parametri invece di restituire una tupla?Questo è in modo da poter avere più sovraccarichi 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 avere costruttori e decostruttori essere "simmetrici" in questo modo. https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
Vecchia risposta:
In effetti, puoi ottenere funzionalità simili in C# utilizzando metodi di estensione come questo (nota:Non ho incluso il controllo 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 puoi usarli in questo modo:
new[] { "hey", "now" }.Match((str1, str2) =>
{
Console.WriteLine(str1);
Console.WriteLine(str2);
});
Nel caso in cui sia necessario un valore restituito da una funzione, funzionerebbe il seguente sovraccarico:
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:
Eviti di dover ripetere il nome dell'array come nella soluzione proposta da JaredPar e altri;l'elenco delle "variabili" è di facile lettura.
Eviti di dover dichiarare esplicitamente i tipi di variabili come nella soluzione di Daniel Earwicker.
Lo svantaggio è che ti ritroverai con un blocco di codice aggiuntivo, ma penso che ne valga la pena.È possibile utilizzare frammenti di codice per evitare di digitare parentesi graffe, ecc.manualmente.
So che è una domanda vecchia di 7 anni, ma non molto tempo fa avevo bisogno di una soluzione del genere: dare facilmente nomi agli elementi dell'array passati nel metodo (no, usare classi/strutture invece di array non era pratico, perché per gli stessi array Potrei aver bisogno di nomi di elementi diversi in metodi diversi) e sfortunatamente mi sono ritrovato con un 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 effetti, ho refactoring uno di questi metodi proprio adesso!):
points.Match((A, A2, B, C2, C) => {...});
La mia soluzione è simile alla corrispondenza dei modelli in F# e sono stato ispirato da questa risposta: https://stackoverflow.com/a/2321922/6659843
Il caso d'uso 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 nell'array e il chiamante li vuole in due variabili separate. È qui che la funzionalità ha più senso:
first_name, last_name = get_info() // always returns an array of length 2
Per esprimerlo in C #, contrassegnare 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ì per chiamarlo:
string firstName, lastName;
SomeClass.GetInfo(out firstName, out lastName);
Non è così carino. Speriamo che qualche versione futura di C # lo consenta:
var firstName, lastName = SomeClass.GetInfo();
Per abilitarlo, il metodo GetInfo
restituisce un Tuple<string, string>
. Si tratterebbe di una modifica continua alla lingua poiché gli attuali usi legali di var
sono molto restrittivi, quindi non è ancora valido per la precedente & Quot; dichiarazione multipla & Quot; sintassi.
Puoi farlo in una riga, ma non come una dichiarazione.
Per esempio:
int str1 = "hey"; int str2 = "now";
Python e Ruby supportano il compito che stai cercando di svolgere;C# no.
Non sono sicuro se quello che voglio è possibile in C #.
Non lo è.
Puoi farlo in C #
string str1 = "hey", str2 = "now";
o puoi essere elegante in questo modo
int x, y;
int[] arr = new int[] { x = 1, y = 2 };
No, ma puoi inizializzare una matrice di stringhe:
string[] strings = new string[] {"hey", "now"};
Anche se probabilmente non è troppo utile per te. Francamente non è difficile metterli su due righe:
string str1 = "hey";
string str2 = "now";
Puoi usare le tuple nominate con C # 7 ora.
{
(string part1, string part2) = Deconstruct(new string[]{"hey","now"});
}
public (string, string) Deconstruct(string[] parts)
{
return (parts[0], parts[1]);
}