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.

È stato utile?

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]);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top