Aktualisierung: In C#7 können Sie problemlos mehrere Variablen auf einmal zuweisen, indem Sie Tupel verwenden. Um Array-Elemente an Variablen zuzuweisen, müssen Sie eine entsprechende Deconstruct()
Erweiterungsmethoden:
Eine andere Möglichkeit, Tupel zu verbrauchen, besteht darin, sie zu dekonstruieren. Eine dekonstruierende Deklaration ist eine Syntax zur Aufteilung eines Tupels (oder eines anderen Wertes) in seine Teile zu zerlegen und diese Teile einzeln neuen Variablen zuzuweisen:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
WriteLine($"found {first} {last}.");
In einer dekonstruierenden Erklärung können Sie var für die einzelnen Variablen deklarieren:
(var first, var middle, var last) = LookupName(id1); // var inside
Oder Sie können auch eine einzelne var außerhalb der Klammern als Abkürzung:
var (first, middle, last) = LookupName(id1); // var outside
Sie können auch in bestehende Variablen dekonstruieren mit einem dekonstruierenden Zuweisung dekonstruieren:
(first, middle, last) = LookupName(id2); // deconstructing assignment
Dekonstruktion ist nicht nur für Tupel geeignet. Jeder Typ kann dekonstruiert werden, solange er eine Dekonstruktionsmethode (Instanz oder Erweiterung) der der Form hat:
public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }
Die Ausgangsparameter sind die Werte, die sich aus den Dekonstruktion ergeben.
(Warum verwendet es out-Parameter, anstatt ein Tupel zurückzugeben? Das ist damit Sie mehrere Überladungen für eine unterschiedliche Anzahl von Werten haben können. Werte haben kann).
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);
Es wird ein gängiges Muster sein, dass Konstruktoren und Dekonstrukteure auf diese Weise "symmetrisch" sind. https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
Alte Antwort:
In der Tat können Sie eine ähnliche Funktionalität in C# erreichen, indem Sie Erweiterungsmethoden wie die folgende verwenden (Hinweis: Ich habe die Überprüfung, ob die Argumente gültig sind, nicht einbezogen):
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]);
}
//...
Und Sie können sie so verwenden:
new[] { "hey", "now" }.Match((str1, str2) =>
{
Console.WriteLine(str1);
Console.WriteLine(str2);
});
Falls ein Rückgabewert von einer Funktion benötigt wird, würde die folgende Überladung funktionieren:
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;
});
}
Auf diese Weise:
-
Sie vermeiden die Wiederholung von Array-Namen wie in der von JaredPar und anderen vorgeschlagenen Lösung; die Liste der "Variablen" ist einfach zu lesen.
-
Sie vermeiden die explizite Deklaration von Variablentypen wie bei der Lösung von Daniel Earwicker.
Der Nachteil ist, dass man am Ende einen zusätzlichen Codeblock hat, aber ich denke, das ist es wert. Sie können Code-Snippets verwenden, um die manuelle Eingabe von geschweiften Klammern usw. zu vermeiden.
Ich weiß, es ist eine 7 Jahre alte Frage, aber nicht so lange Zeit vor ich brauchte eine solche Lösung - einfach geben Namen zu Array-Elemente in die Methode übergeben (nein, mit Klassen/Strukturen anstelle von Arrays war nicht praktisch, weil für gleiche Arrays ich unterschiedliche Elementnamen in verschiedenen Methoden benötigen könnte) und leider landete ich mit Code wie diese:
var A = points[0];
var A2 = points[1];
var B = points[2];
var C2 = points[3];
var C = points[4];
Jetzt könnte ich schreiben (in der Tat habe ich eine dieser Methoden gerade überarbeitet!):
points.Match((A, A2, B, C2, C) => {...});
Meine Lösung ähnelt dem Musterabgleich in F#, und ich wurde von dieser Antwort inspiriert: https://stackoverflow.com/a/2321922/6659843
4 Stimmen
Wow, hässlich und verwirrend. Erinnert mich an mein letztes Date.
3 Stimmen
@Will: Really? Ich denke, es ist schön und prägnant, aber trotzdem klar und lesbar. Ich mag die Funktion in Python sehr und verwende sie häufig.
1 Stimmen
Aus Sicht von C# auf jeden Fall. Es sieht so aus, als würden Sie einen Verweis auf ein einzelnes Array zwei verschiedenen Variablen zuweisen... wie str1 = new string[] {"one", "two"}; str2 = str1; Also ist es für C#-Entwickler sofort verwirrend. Der hässliche Teil war nur, damit ich den Witz unterbringen konnte.
5 Stimmen
Vielleicht, wenn C# ist Ihre einzige Sprache, dann ja, ich nehme an, es sieht ein bisschen hässlich. Vielleicht sollten Sie darüber nachdenken, Ihren Horizont zu erweitern? Wie auch immer, obwohl ich nie in Ruby entwickelt habe, habe ich eine Menge in Python getan, so dass diese Aufgabe ist nicht neu für mich überhaupt. Es sieht aus wie eine einfache Tupel-Erstellung und ein Entpacken (auch Tupel-Zuweisung genannt). Obwohl Ruby offenbar Klammern [] statt Parens () wie Python verwendet, ist es ansonsten syntaktisch identisch. Aufgrund der Kommentare von @Sarah gehe ich davon aus, dass es identisch funktioniert.
0 Stimmen
Ich glaube, Will bezieht sich auf den Befehlszeilenteil des Beispiels. Da ich noch nie mit Ruby gearbeitet habe, war ich selbst etwas verwirrt. Die Aufgabe selbst ist kurz, klar und gut lesbar.