Gibt es eine Möglichkeit, eine Tupel-Klasse zu verwenden, aber die Namen der darin enthaltenen Elemente anzugeben?
Beispielsweise:
public Tuple<int, int, int int> GetOrderRelatedIds()
Dadurch werden die IDs für OrderGroupId, OrderTypeId, OrderSubTypeId und OrderRequirementId zurückgegeben.
Es wäre schön, die Benutzer meiner Methode wissen zu lassen, welche welche ist. (Wenn Sie die Methode aufrufen, sind die Ergebnisse result.Item1, result.Item2, result.Item3, result.Item4. Es ist nicht klar, welches welches ist.)
(Ich weiß, ich könnte einfach eine Klasse erstellen, die alle diese IDs enthält, aber diese IDs haben bereits ihre eigenen Klassen, in denen sie leben, und eine Klasse für den Rückgabewert dieser einen Methode zu erstellen, scheint dumm.)
Tuple
ist sehr allgemein gehalten, das ist alles, was du bekommstAntworten:
In C # 7.0 (Visual Studio 2017) gibt es dafür eine neue Konstruktion:
quelle
List<(int first, int second)>
. Ich musste das System.ValueTuple-Paket von NuGet herunterladen, damit es in Visual Studio 2017 funktioniert.return (first: first, middle: middle, last: last);
return (first, middle, last);
in .NET 4.7.1 (nicht sicher für 4.7.0)ValueTuple
, obwohl normalerweise großartig, ein veränderbarer Werttyp (struct) ist, währendTuple
es ein unveränderlicher Referenztyp (Klasse) ist. Soweit ich weiß, gibt es keine Möglichkeit, einen ReferenztypTuple
mit benutzerfreundlichen Artikelnamen zu erhalten.Bis C # 7.0 gab es keine Möglichkeit, dies zu tun, ohne Ihren eigenen Typ zu definieren.
quelle
Hier ist eine übermäßig komplizierte Version dessen, was Sie fragen:
Warum nicht einfach eine Klasse machen?
quelle
Tuple<T, T2>
Sie keine Struktur sein.Mit .net 4 könnten Sie sich vielleicht das ansehen
ExpandoObject
, verwenden Sie es jedoch nicht für diesen einfachen Fall, da aus Fehlern bei der Kompilierung Laufzeitfehler werden.Etwas anderes Erwähnenswertes ist ein anonymer Typ innerhalb einer Methode , aber Sie müssen eine Klasse erstellen, wenn Sie sie zurückgeben möchten.
quelle
Ich reproduziere meine Antwort aus diesem Beitrag, da sie hier besser passt.
Ab C # v7.0, jetzt ist es möglich , die Tupel Eigenschaften zu nennen , die auf vordefinierte Namen zu Standard früher verwendet werden , wie
Item1
,Item2
und so weiter.Benennen der Eigenschaften von Tupel-Literalen :
Die Ausgabe auf der Konsole:
Rückgabe von Tupel (mit benannten Eigenschaften) von einer Methode :
Die Ausgabe auf der Konsole:
Erstellen einer Liste von Tupeln mit benannten Eigenschaften
Ausgabe auf der Konsole:
Ich hoffe ich habe alles abgedeckt. Falls ich etwas verpasst habe, gib mir bitte ein Feedback in den Kommentaren.
Hinweis : Mein Code - Schnipsel verwendet String Interpolationsmerkmal von v7 C # wie detailliert hier .
quelle
MichaelMocko Beantwortet ist großartig,
aber ich möchte ein paar Dinge hinzufügen, die ich herausfinden musste
Die obige Zeile gibt Ihnen einen Fehler bei der Kompilierung, wenn Sie das .net Framework <4.7 verwenden
Wenn Sie also ein Projekt haben, das .net Framework <4.7 verwendet, und dennoch ValueTuple verwenden möchten, würde workAround dieses Nuget-Paket installieren
quelle
Nein, Sie können die Tupelmitglieder nicht benennen.
Dazwischen würde ExpandoObject anstelle von Tuple verwendet.
quelle
Wenn die Arten Ihrer Artikel alle unterschiedlich sind, habe ich eine Klasse erstellt, um sie intuitiver zu gestalten.
Die Verwendung dieser Klasse:
Quellcode:
quelle
Dies ist sehr ärgerlich und ich gehe davon aus, dass zukünftige Versionen von C # diesen Bedarf decken werden. Ich finde es am einfachsten, entweder einen anderen Datenstrukturtyp zu verwenden oder die "Elemente" für Ihre Gesundheit und für die Gesundheit anderer, die Ihren Code lesen, umzubenennen.
quelle
Ich denke, ich würde eine Klasse erstellen, aber eine andere Alternative sind Ausgabeparameter.
Da Ihr Tupel nur Ganzzahlen enthält, können Sie es mit a darstellen
Dictionary<string,int>
aber das empfehle ich auch nicht.
quelle
Warum machen alle das Leben so schwer? Tupel dienen eher der temporären Datenverarbeitung. Wenn Sie ständig mit Tupeln arbeiten, ist der Code irgendwann sehr schwer zu verstehen. Das Erstellen von Klassen für alles könnte Ihr Projekt möglicherweise aufblähen.
Es geht jedoch um Balance ...
Ihr Problem scheint etwas zu sein, für das Sie eine Klasse wollen würden. Der Vollständigkeit halber enthält diese Klasse auch Konstruktoren.
Dies ist das richtige Muster für
Oder, wenn Sie es wirklich einfach wollen: Sie können auch Typinitialisierer verwenden:
quelle
Ich würde die Item-Namen in die Zusammenfassung schreiben. Wenn Sie also mit der Maus über die Funktion helloworld () fahren, sagt der Text Hallo = Item1 und Welt = Item2
quelle
Nur um @MichaelMocko Antwort hinzuzufügen. Tupel haben im Moment ein paar Fallstricke:
Sie können sie nicht in EF-Ausdrucksbäumen verwenden
Beispiel:
Dies kann nicht mit dem Fehler "Ein Ausdrucksbaum enthält möglicherweise kein Tupelliteral" kompiliert werden. Leider wurde die API für Ausdrucksbäume nicht mit Unterstützung für Tupel erweitert, als diese der Sprache hinzugefügt wurden.
Verfolgen (und verbessern) Sie dieses Problem für die Updates: https://github.com/dotnet/roslyn/issues/12897
Um das Problem zu umgehen, können Sie es zuerst in einen anonymen Typ umwandeln und dann den Wert in Tupel konvertieren:
Eine weitere Option ist die Verwendung von ValueTuple.Create:
Verweise:
https://www.damirscorner.com/blog/posts/20181207-NoSupportForTuplesInExpressionTrees.html
Konvertieren Sie einen anonymen Typ in einen neuen C # 7-Tupeltyp
Sie können sie nicht in Lambdas dekonstruieren
Es gibt einen Vorschlag, die Unterstützung hinzuzufügen: https://github.com/dotnet/csharplang/issues/258
Beispiel:
Verweise:
Sie werden nicht gut serialisiert
Tupelfeldnamen sind nur zur Kompilierungszeit verfügbar und werden zur Laufzeit vollständig gelöscht.
Verweise:
quelle
Sie können eine Klasse schreiben, die das Tupel enthält.
Sie müssen die Funktionen Equals und GetHashCode überschreiben
und die Operatoren == und! =.
wird zurückkehren:
Wahr
Wahr
quelle
Beispiel für ein C # 7-Tupel
quelle