Praktisches Beispiel, wo Tuple in .Net 4.0 verwendet werden kann?
97
Ich habe das in .Net 4 eingeführte Tupel gesehen, kann mir aber nicht vorstellen, wo es verwendet werden kann. Wir können immer eine benutzerdefinierte Klasse oder Struktur erstellen.
Vielleicht ist dies ein guter Ort, um festzustellen, dass dieses Thema sehr alt ist. Schauen Sie, was in C # 7 passiert ist !
Maf-Soft
Antworten:
83
Das ist der Punkt - es ist bequemer, nicht ständig eine benutzerdefinierte Klasse oder Struktur zu erstellen. Es ist eine Verbesserung wie Actionoder Func... Sie können diese Typen selbst erstellen, aber es ist praktisch, dass sie im Framework vorhanden sind.
Wahrscheinlich ist es wert, von MSDN darauf hingewiesen zu werden : "Alle öffentlichen statischen Mitglieder dieses Typs sind threadsicher. Es wird nicht garantiert, dass Instanzmitglieder threadsicher sind. "
Matt Borja
Vielleicht hätten die Sprachdesigner es dann einfacher machen sollen, benutzerdefinierte Typen im laufenden Betrieb zu erstellen? Also könnten wir die gleiche Syntax beibehalten, anstatt noch eine einzuführen?
Thomas Eyde
@ThomasEyde, genau das machen sie seit 15 Jahren. Auf diese Weise wurden Mitglieder mit Ausdruckskörper hinzugefügt, die jetzt Tupel wertschätzen. Klassen im Rekordstil haben den Rückgang im August (9 Monate vor diesem Kommentar) für diese Version von C # 7 nur knapp verpasst und werden wahrscheinlich in C # 8 veröffentlicht. Beachten Sie auch, dass Wertetupel Wertgleichheit bieten, wo einfache alte Klassen dies nicht tun . Die Einführung all dessen im Jahr 2002 würde
Gewissen
was meinst du convenient not to make a custom class. Meinen Sie damit, eine benutzerdefinierte Klasseninstanz mit zu erstellen =new..()?
Alex
75
Mit Tupeln können Sie leicht ein zweidimensionales Wörterbuch (oder n-dimensional) implementieren. Sie könnten beispielsweise ein solches Wörterbuch verwenden, um eine Währungsumtauschzuordnung zu implementieren:
Ich würde lieber eine Aufzählung für die Länderabkürzungen verwenden. Ist das möglich?
Zack
1
Sicher, es sollte ohne Probleme funktionieren, da Aufzählungen Werttypen sind.
MarioVW
@MarioVW Dies könnte auch mit einem mehrdimensionalen Array erreicht werden. Wie Tupel macht einen Unterschied?
Alex
26
Es gibt einen ausgezeichneten Artikel im MSDN-Magazin, der über die Bauchschmerzen und Designüberlegungen spricht, die beim Hinzufügen von Tuple zur BCL auftraten. Besonders interessant ist die Wahl zwischen einem Werttyp und einem Referenztyp.
Wie der Artikel deutlich macht, waren die treibenden Kräfte hinter Tuple so viele Gruppen innerhalb von Microsoft, die eine Verwendung dafür hatten, das F # -Team vorne. Obwohl nicht erwähnt, denke ich, dass das neue "dynamische" Schlüsselwort in C # (und VB.NET) auch etwas damit zu tun hat. Tupel sind in dynamischen Sprachen sehr verbreitet.
Ansonsten ist es nicht besonders überlegen, einen eigenen Poco zu kreieren, zumindest können Sie den Mitgliedern einen besseren Namen geben.
UPDATE: Aufgrund einer großen Überarbeitung in C # Version 7, die jetzt viel mehr Liebe zur Syntax bietet. Vorläufige Ankündigung in diesem Blogbeitrag .
Hier ist ein kleines Beispiel: Angenommen, Sie haben eine Methode, mit der das Handle und die E-Mail-Adresse eines Benutzers unter Angabe einer Benutzer-ID nachgeschlagen werden müssen. Sie können jederzeit eine benutzerdefinierte Klasse erstellen, die diese Daten enthält, oder einen ref / out-Parameter für diese Daten verwenden, oder Sie können einfach ein Tupel zurückgeben und eine schöne Methodensignatur haben, ohne einen neuen POCO erstellen zu müssen.
Dies ist ein gutes Beispiel, rechtfertigt jedoch nicht die Verwendung von Tupel.
Amitabh
7
Ein Tupel passt hier gut, da Sie unterschiedliche Werte zurückgeben. Ein Tupel leuchtet jedoch stärker, wenn Sie mehrere Werte unterschiedlichen Typs zurückgeben .
Mark Rushakoff
21
Ein weiteres gutes Beispiel wäre int.TryParse, da Sie den Ausgabeparameter entfernen und stattdessen ein Tupel verwenden könnten. Sie könnten also haben Tuple<bool, T> TryParse<T>(string input)und anstatt einen Ausgabeparameter verwenden zu müssen, erhalten Sie beide Werte in einem Tupel zurück.
Tejs
3
Genau das passiert, wenn Sie eine TryParse-Methode von F # aus aufrufen.
classGrid{publicstaticint[,]Cells={{08,02,22,// whole grid omittedpublicstaticIEnumerable<Tuple<int,int,int,int>>ToList(){// code converts grid to enumeration every possible set of 4 per rules// code omitted}}
Die Tupelsyntax von C # ist lächerlich umfangreich, daher ist es schmerzhaft, Tupel zu deklarieren. Und es gibt keine Musterübereinstimmung, so dass die Verwendung auch schmerzhaft ist.
Gelegentlich möchten Sie jedoch nur eine Ad-hoc-Gruppierung von Objekten, ohne eine Klasse dafür zu erstellen. Nehmen wir zum Beispiel an, ich wollte eine Liste aggregieren, aber ich wollte zwei Werte anstelle von einem:
// sum and sum of squares at the same timevar x =Enumerable.Range(1,100).Aggregate((acc, x)=>Tuple.Create(acc.Item1+ x, acc.Item2+ x * x));
Anstatt eine Sammlung von Werten zu einem einzigen Ergebnis zu kombinieren, erweitern wir ein einzelnes Ergebnis zu einer Sammlung von Werten. Der einfachste Weg, diese Funktion zu schreiben, ist:
fwandelt einen Zustand in ein Tupel um. Wir geben den ersten Wert aus dem Tupel zurück und setzen unseren neuen Status auf den zweiten Wert. Dies ermöglicht es uns, den Status während der gesamten Berechnung beizubehalten.
Sie verwenden es als solches:
// return 0, 2, 3, 6, 8var evens =Unfold(0, state => state <10?Tuple.Create(state, state +2):null).ToList();// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34var fibs =Unfold(Tuple.Create(0,1), state =>Tuple.Create(state.Item1,Tuple.Create(state.Item2, state.Item1+ state.Item2))).Take(10).ToList();
evensist ziemlich einfach, aber fibsetwas schlauer. Es stateist eigentlich ein Tupel, das fib (n-2) bzw. fib (n-1) enthält.
+1 Tuple.Create ist eine praktische Abkürzung fürnew Tuple<Guid,string,...>
AaronLS
@ Julia Was die Verwendung von State-Schlüsselwort
irfandar
7
Ich mag ihren Missbrauch nicht, da sie Code produzieren, der sich nicht selbst erklärt, aber es ist großartig, zusammengesetzte Schlüssel im laufenden Betrieb zu implementieren, da sie IStructuralEquatable und IStructuralComparable implementieren (um sowohl zum Nachschlagen als auch zum Bestellen zu verwenden Zwecke).
Und sie kombinieren alle Hashcodes ihrer Artikel intern. Hier ist zum Beispiel Tuples GetHashCode (aus ILSpy):
Tupel eignen sich hervorragend, um mehrere asynchrone E / A-Vorgänge gleichzeitig auszuführen und alle Werte zusammen zurückzugeben. Hier sind die Beispiele dafür mit und ohne Tupel. Tupel können Ihren Code tatsächlich klarer machen!
Wenn Sie ohnehin eine anonyme Funktion mit einem impliziten Typ verwendet haben, machen Sie den Code mit dem Tupel nicht weniger klar. Ein Tupel von einer Methode neu abstimmen? Verwenden Sie es meiner bescheidenen Meinung nach sparsam, wenn die Klarheit des Codes entscheidend ist. Ich weiß, dass funktionale Programmierung in C # schwer zu widerstehen ist, aber wir müssen all diese alten klobigen "objektorientierten" C # -Programmierer berücksichtigen.
Tupel werden häufig in funktionalen Sprachen verwendet, die mehr mit ihnen tun können. Jetzt ist F # eine 'offizielle' .net-Sprache, mit der Sie möglicherweise von C # aus zusammenarbeiten und sie zwischen in zwei Sprachen geschriebenem Code weitergeben möchten.
Tupel sind auch in Typen für einige gängige Skriptsprachen wie Python und Ruby integriert (die auch .NET-Implementierungen für Interop ... IronPython / Ruby enthalten).
MutantNinjaCodeMonkey
5
Ich neige dazu, Tuplefür die meisten Szenarien zu vermeiden , da es die Lesbarkeit beeinträchtigt. Dies Tupleist jedoch nützlich, wenn Sie nicht verwandte Daten gruppieren müssen.
Angenommen, Sie haben eine Liste der Autos und der Städte, in denen sie gekauft wurden:
Dazu erstellen Sie eine Dictionary. Sie haben einige Möglichkeiten:
Erstellen Sie eine Dictionary<string, Dictionary<string, int>>.
Erstellen Sie eine Dictionary<CarAndCity, int>.
Erstellen Sie eine Dictionary<Tuple<string, string>, int>.
Die Lesbarkeit geht mit der ersten Option verloren. Sie müssen viel mehr Code schreiben.
Die zweite Option funktioniert und ist prägnant, aber Auto und Stadt sind nicht wirklich miteinander verbunden und gehören wahrscheinlich nicht zusammen in eine Klasse.
Die dritte Option ist prägnant und sauber. Es ist eine gute Verwendung von Tuple.
Tupleist in kritischen Situationen genauso praktisch wie Pointoder SomeVectorkann bei Grafikoperationen nützlich sein. Es werden zwei Werte hervorgehoben, die sehr eng miteinander verbunden sind. Beim Lesen von Code werden häufig Eigenschaften mit den Namen StartTime und EndTime angezeigt. Noch besser als eine Datums- und Uhrzeitangabe und eine Dauer. Ein Tupel zwingt Sie jedoch, beide Werte jedes Mal zu berücksichtigen, wenn Sie in diesem Bereich Ihrer Geschäftslogik arbeiten. Oder die Rückgabe "Hey, Daten haben sich geändert (bool), hier sind die Daten (anderer Typ)" in stark verarbeiteten Daten, anstatt intensive Bindungen zu durchlaufen.
Léon Pelletier
3
Sie sollten sehr vorsichtig mit der Verwendung sein Tupleund wahrscheinlich zweimal überlegen, bevor Sie dies tun. Aus meinen früheren Erfahrungen habe ich herausgefunden, dass die Verwendung von TupleCode das Lesen und Unterstützen von Code in Zukunft sehr schwierig macht. Vor einiger Zeit musste ich einen Code reparieren, in dem fast überall Tupel verwendet wurden. Anstatt über richtige Objektmodelle nachzudenken, verwendeten sie nur Tupel. Das war ein Albtraum ... manchmal wollte ich den Kerl töten, der den Code geschrieben hat ...
Ich möchte nicht sagen, dass Sie nicht verwenden sollten Tupleund es ist böse oder so und ich bin hundertprozentig sicher, dass es einige Aufgaben gibt, bei denen Tupleder beste Kandidat verwendet werden kann, aber wahrscheinlich sollten Sie noch einmal darüber nachdenken, ob Sie ihn WIRKLICH brauchen ?
Die beste Verwendung für Tupel, die ich gefunden habe, ist, wenn Sie mehr als einen Objekttyp von einer Methode zurückgeben müssen, Sie wissen, welche Objekttypen und -nummern sie sein werden, und es ist keine lange Liste.
Andere einfache Alternativen wären die Verwendung eines 'out'-Parameters
privatestringMyMethod(outobject)
oder ein Wörterbuch erstellen
Dictionary<objectType1, objectType2>
Die Verwendung eines Tupels erspart jedoch das Erstellen des 'out'-Objekts oder das wesentliche Nachschlagen des Eintrags im Wörterbuch.
Habe gerade die Lösung eines meiner Probleme in Tuple gefunden. Es ist wie das Deklarieren einer Klasse im Bereich einer Methode, jedoch mit einer verzögerten Deklaration ihrer Feldnamen. Sie arbeiten mit Sammlungen von Tupeln, ihren einzelnen Instanzen, und erstellen dann eine Sammlung von anonymem Typ mit den erforderlichen Feldnamen, basierend auf Ihrem Tupel. Dadurch wird vermieden, dass Sie die neue Klasse für diesen Zweck erstellen.
Die Aufgabe besteht darin, eine JSON-Antwort von LINQ ohne zusätzliche Klassen zu schreiben:
//I select some roles from my ORM my with subrequest and save results to Tuple listvar rolesWithUsers =(from role in roles
selectnewTuple<string,int,int>(
role.RoleName,
role.RoleId,
usersInRoles.Where(ur => ur.RoleId== role.RoleId).Count()));//Then I add some new element required element to this collectionvar tempResult = rolesWithUsers.ToList();
tempResult.Add(newTuple<string,int,int>("Empty",-1,
emptyRoleUsers.Count()));//And create a new anonimous class collection, based on my Tuple list
tempResult.Select(item =>new{GroupName= item.Item1,GroupId= item.Item2,Count= item.Item3});//And return it in JSONreturnnewJavaScriptSerializer().Serialize(rolesWithUsers);
Natürlich könnten wir dies tun, indem wir eine neue Klasse für meine Gruppen deklarieren, aber die Idee, solch anonyme Sammlungen zu erstellen, ohne neue Klassen zu deklarieren.
In meinem Fall musste ich ein Tupel verwenden, als ich herausfand, dass wir den Parameter out in einer asynchronen Methode nicht verwenden können. Lesen Sie hier darüber . Ich brauchte auch einen anderen Rückgabetyp. Also habe ich stattdessen ein Tupel als Rückgabetyp verwendet und die Methode als asynchron markiert.
Beispielcode unten.
......// calling code.var userDetails =awaitGetUserDetails(userId);Console.WriteLine("Username : {0}", userDetails.Item1);Console.WriteLine("User Region Id : {0}", userDetails.Item2);......privateasyncTuple<string,int>GetUserDetails(int userId){returnnewTuple<string,int>("Amogh",105);// Note that I can also use the existing helper method (Tuple.Create).}
Ändern von Objektformen, wenn Sie sie über Kabel senden oder an eine andere Anwendungsebene übergeben müssen und mehrere Objekte zu einem zusammengeführt werden:
Beispiel:
var customerDetails =newTuple<Customer,List<Address>>(mainCustomer,newList<Address>{mainCustomerAddress}).ToCustomerDetails();
Ein out-Parameter ist ideal, wenn nur wenige Werte zurückgegeben werden müssen. Wenn Sie jedoch auf 4, 5, 6 oder mehr Werte stoßen, die zurückgegeben werden müssen, kann dies unhandlich werden. Eine weitere Option zum Zurückgeben mehrerer Werte besteht darin, eine benutzerdefinierte Klasse / Struktur zu erstellen und zurückzugeben oder ein Tupel zu verwenden, um alle Werte zu verpacken, die von einer Methode zurückgegeben werden müssen.
Die erste Option, bei der eine Klasse / Struktur zum Zurückgeben der Werte verwendet wird, ist unkompliziert. Erstellen Sie einfach den Typ (in diesem Beispiel ist es eine Struktur) wie folgt:
Die zweite Option, ein Tupel zu verwenden, ist eine noch elegantere Lösung als die Verwendung eines benutzerdefinierten Objekts. Es kann ein Tupel erstellt werden, das eine beliebige Anzahl von Werten unterschiedlichen Typs enthält. Darüber hinaus sind die Daten, die Sie im Tupel speichern, unveränderlich. Sobald Sie die Daten über den Konstruktor oder die statische Create-Methode zum Tupel hinzugefügt haben, können diese Daten nicht mehr geändert werden. Tupel können bis zu acht separate Werte akzeptieren. Wenn Sie mehr als acht Werte zurückgeben müssen, müssen Sie die spezielle Tupelklasse verwenden: Tupelklasse Wenn Sie ein Tupel mit mehr als acht Werten erstellen, können Sie die statische Create-Methode nicht verwenden. Sie müssen stattdessen den Konstruktor der Klasse verwenden. So würden Sie ein Tupel mit 10 ganzzahligen Werten erstellen:
var values =newTuple<int,int,int,int,int,int,int,Tuple<int,int,int>>(1,2,3,4,5,6,7,newTuple<int,int,int>(8,9,10));
Natürlich können Sie am Ende jedes eingebetteten Tupels weitere Tupel hinzufügen und so ein beliebiges Tupel erstellen.
Nur für das Prototyping - Tupel sind bedeutungslos. Es ist bequem, sie zu benutzen, aber es ist nur eine Abkürzung! Für Prototypen - gut. Löschen Sie diesen Code später unbedingt.
Es ist leicht zu schreiben, schwer zu lesen. Es hat keine sichtbaren Vorteile gegenüber Klassen, inneren Klassen, anonymen Klassen usw.
Nun, ich habe drei Möglichkeiten ausprobiert, um das gleiche Problem in C # 7 zu lösen, und ich habe einen Anwendungsfall für Tuples gefunden.
Das Arbeiten mit dynamischen Daten in Webprojekten kann beim Mapping usw. manchmal schwierig sein.
Ich mag die Art und Weise, wie das Tupel nur automatisch auf item1, item2, itemN abgebildet wird, was mir robuster erscheint als die Verwendung von Array-Indizes, bei denen Sie möglicherweise auf ein Element außerhalb des Indexes stoßen, oder die Verwendung des anonymen Typs, bei dem Sie möglicherweise einen Eigenschaftsnamen falsch schreiben.
Es fühlt sich so an, als ob ein DTO nur mit einem Tupel kostenlos erstellt wurde, und ich kann mit itemN auf alle Eigenschaften zugreifen, was eher wie statische Eingabe aussieht, ohne dass zu diesem Zweck ein separates DTO erstellt werden muss.
Antworten:
Das ist der Punkt - es ist bequemer, nicht ständig eine benutzerdefinierte Klasse oder Struktur zu erstellen. Es ist eine Verbesserung wie
Action
oderFunc
... Sie können diese Typen selbst erstellen, aber es ist praktisch, dass sie im Framework vorhanden sind.quelle
convenient not to make a custom class
. Meinen Sie damit, eine benutzerdefinierte Klasseninstanz mit zu erstellen=new..()
?Mit Tupeln können Sie leicht ein zweidimensionales Wörterbuch (oder n-dimensional) implementieren. Sie könnten beispielsweise ein solches Wörterbuch verwenden, um eine Währungsumtauschzuordnung zu implementieren:
quelle
Es gibt einen ausgezeichneten Artikel im MSDN-Magazin, der über die Bauchschmerzen und Designüberlegungen spricht, die beim Hinzufügen von Tuple zur BCL auftraten. Besonders interessant ist die Wahl zwischen einem Werttyp und einem Referenztyp.
Wie der Artikel deutlich macht, waren die treibenden Kräfte hinter Tuple so viele Gruppen innerhalb von Microsoft, die eine Verwendung dafür hatten, das F # -Team vorne. Obwohl nicht erwähnt, denke ich, dass das neue "dynamische" Schlüsselwort in C # (und VB.NET) auch etwas damit zu tun hat. Tupel sind in dynamischen Sprachen sehr verbreitet.
Ansonsten ist es nicht besonders überlegen, einen eigenen Poco zu kreieren, zumindest können Sie den Mitgliedern einen besseren Namen geben.
UPDATE: Aufgrund einer großen Überarbeitung in C # Version 7, die jetzt viel mehr Liebe zur Syntax bietet. Vorläufige Ankündigung in diesem Blogbeitrag .
quelle
Hier ist ein kleines Beispiel: Angenommen, Sie haben eine Methode, mit der das Handle und die E-Mail-Adresse eines Benutzers unter Angabe einer Benutzer-ID nachgeschlagen werden müssen. Sie können jederzeit eine benutzerdefinierte Klasse erstellen, die diese Daten enthält, oder einen ref / out-Parameter für diese Daten verwenden, oder Sie können einfach ein Tupel zurückgeben und eine schöne Methodensignatur haben, ohne einen neuen POCO erstellen zu müssen.
quelle
Tuple<bool, T> TryParse<T>(string input)
und anstatt einen Ausgabeparameter verwenden zu müssen, erhalten Sie beide Werte in einem Tupel zurück.Ich habe ein Tupel verwendet, um Problem 11 von Project Euler zu lösen :
Jetzt kann ich das ganze Problem lösen mit:
Ich hätte einen benutzerdefinierten Typ dafür verwenden können, aber er hätte genau wie Tupel ausgesehen .
quelle
Die Tupelsyntax von C # ist lächerlich umfangreich, daher ist es schmerzhaft, Tupel zu deklarieren. Und es gibt keine Musterübereinstimmung, so dass die Verwendung auch schmerzhaft ist.
Gelegentlich möchten Sie jedoch nur eine Ad-hoc-Gruppierung von Objekten, ohne eine Klasse dafür zu erstellen. Nehmen wir zum Beispiel an, ich wollte eine Liste aggregieren, aber ich wollte zwei Werte anstelle von einem:
Anstatt eine Sammlung von Werten zu einem einzigen Ergebnis zu kombinieren, erweitern wir ein einzelnes Ergebnis zu einer Sammlung von Werten. Der einfachste Weg, diese Funktion zu schreiben, ist:
f
wandelt einen Zustand in ein Tupel um. Wir geben den ersten Wert aus dem Tupel zurück und setzen unseren neuen Status auf den zweiten Wert. Dies ermöglicht es uns, den Status während der gesamten Berechnung beizubehalten.Sie verwenden es als solches:
evens
ist ziemlich einfach, aberfibs
etwas schlauer. Esstate
ist eigentlich ein Tupel, das fib (n-2) bzw. fib (n-1) enthält.quelle
new Tuple<Guid,string,...>
Ich mag ihren Missbrauch nicht, da sie Code produzieren, der sich nicht selbst erklärt, aber es ist großartig, zusammengesetzte Schlüssel im laufenden Betrieb zu implementieren, da sie IStructuralEquatable und IStructuralComparable implementieren (um sowohl zum Nachschlagen als auch zum Bestellen zu verwenden Zwecke).
Und sie kombinieren alle Hashcodes ihrer Artikel intern. Hier ist zum Beispiel Tuples GetHashCode (aus ILSpy):
quelle
Tupel eignen sich hervorragend, um mehrere asynchrone E / A-Vorgänge gleichzeitig auszuführen und alle Werte zusammen zurückzugeben. Hier sind die Beispiele dafür mit und ohne Tupel. Tupel können Ihren Code tatsächlich klarer machen!
Ohne (böse Verschachtelung!):
Mit Tupel
Wenn Sie ohnehin eine anonyme Funktion mit einem impliziten Typ verwendet haben, machen Sie den Code mit dem Tupel nicht weniger klar. Ein Tupel von einer Methode neu abstimmen? Verwenden Sie es meiner bescheidenen Meinung nach sparsam, wenn die Klarheit des Codes entscheidend ist. Ich weiß, dass funktionale Programmierung in C # schwer zu widerstehen ist, aber wir müssen all diese alten klobigen "objektorientierten" C # -Programmierer berücksichtigen.
quelle
Tupel werden häufig in funktionalen Sprachen verwendet, die mehr mit ihnen tun können. Jetzt ist F # eine 'offizielle' .net-Sprache, mit der Sie möglicherweise von C # aus zusammenarbeiten und sie zwischen in zwei Sprachen geschriebenem Code weitergeben möchten.
quelle
Ich neige dazu,
Tuple
für die meisten Szenarien zu vermeiden , da es die Lesbarkeit beeinträchtigt. DiesTuple
ist jedoch nützlich, wenn Sie nicht verwandte Daten gruppieren müssen.Angenommen, Sie haben eine Liste der Autos und der Städte, in denen sie gekauft wurden:
Sie möchten die Anzahl für jedes Auto pro Stadt aggregieren:
Dazu erstellen Sie eine
Dictionary
. Sie haben einige Möglichkeiten:Dictionary<string, Dictionary<string, int>>
.Dictionary<CarAndCity, int>
.Dictionary<Tuple<string, string>, int>
.Die Lesbarkeit geht mit der ersten Option verloren. Sie müssen viel mehr Code schreiben.
Die zweite Option funktioniert und ist prägnant, aber Auto und Stadt sind nicht wirklich miteinander verbunden und gehören wahrscheinlich nicht zusammen in eine Klasse.
Die dritte Option ist prägnant und sauber. Es ist eine gute Verwendung von
Tuple
.quelle
Ein paar Beispiele aus meinem Kopf:
Zum Beispiel möchten Sie System.Drawing nicht in eine Webanwendung aufnehmen, nur um Point / PointF und Size / SizeF zu verwenden.
quelle
Tuple
ist in kritischen Situationen genauso praktisch wiePoint
oderSomeVector
kann bei Grafikoperationen nützlich sein. Es werden zwei Werte hervorgehoben, die sehr eng miteinander verbunden sind. Beim Lesen von Code werden häufig Eigenschaften mit den Namen StartTime und EndTime angezeigt. Noch besser als eine Datums- und Uhrzeitangabe und eine Dauer. Ein Tupel zwingt Sie jedoch, beide Werte jedes Mal zu berücksichtigen, wenn Sie in diesem Bereich Ihrer Geschäftslogik arbeiten. Oder die Rückgabe "Hey, Daten haben sich geändert (bool), hier sind die Daten (anderer Typ)" in stark verarbeiteten Daten, anstatt intensive Bindungen zu durchlaufen.Sie sollten sehr vorsichtig mit der Verwendung sein
Tuple
und wahrscheinlich zweimal überlegen, bevor Sie dies tun. Aus meinen früheren Erfahrungen habe ich herausgefunden, dass die Verwendung vonTuple
Code das Lesen und Unterstützen von Code in Zukunft sehr schwierig macht. Vor einiger Zeit musste ich einen Code reparieren, in dem fast überall Tupel verwendet wurden. Anstatt über richtige Objektmodelle nachzudenken, verwendeten sie nur Tupel. Das war ein Albtraum ... manchmal wollte ich den Kerl töten, der den Code geschrieben hat ...Ich möchte nicht sagen, dass Sie nicht verwenden sollten
Tuple
und es ist böse oder so und ich bin hundertprozentig sicher, dass es einige Aufgaben gibt, bei denenTuple
der beste Kandidat verwendet werden kann, aber wahrscheinlich sollten Sie noch einmal darüber nachdenken, ob Sie ihn WIRKLICH brauchen ?quelle
Die beste Verwendung für Tupel, die ich gefunden habe, ist, wenn Sie mehr als einen Objekttyp von einer Methode zurückgeben müssen, Sie wissen, welche Objekttypen und -nummern sie sein werden, und es ist keine lange Liste.
Andere einfache Alternativen wären die Verwendung eines 'out'-Parameters
oder ein Wörterbuch erstellen
Die Verwendung eines Tupels erspart jedoch das Erstellen des 'out'-Objekts oder das wesentliche Nachschlagen des Eintrags im Wörterbuch.
quelle
Habe gerade die Lösung eines meiner Probleme in Tuple gefunden. Es ist wie das Deklarieren einer Klasse im Bereich einer Methode, jedoch mit einer verzögerten Deklaration ihrer Feldnamen. Sie arbeiten mit Sammlungen von Tupeln, ihren einzelnen Instanzen, und erstellen dann eine Sammlung von anonymem Typ mit den erforderlichen Feldnamen, basierend auf Ihrem Tupel. Dadurch wird vermieden, dass Sie die neue Klasse für diesen Zweck erstellen.
Die Aufgabe besteht darin, eine JSON-Antwort von LINQ ohne zusätzliche Klassen zu schreiben:
Natürlich könnten wir dies tun, indem wir eine neue Klasse für meine Gruppen deklarieren, aber die Idee, solch anonyme Sammlungen zu erstellen, ohne neue Klassen zu deklarieren.
quelle
In meinem Fall musste ich ein Tupel verwenden, als ich herausfand, dass wir den Parameter out in einer asynchronen Methode nicht verwenden können. Lesen Sie hier darüber . Ich brauchte auch einen anderen Rückgabetyp. Also habe ich stattdessen ein Tupel als Rückgabetyp verwendet und die Methode als asynchron markiert.
Beispielcode unten.
Lesen Sie hier mehr über Tuple . Hoffe das hilft.
quelle
Ändern von Objektformen, wenn Sie sie über Kabel senden oder an eine andere Anwendungsebene übergeben müssen und mehrere Objekte zu einem zusammengeführt werden:
Beispiel:
ExtensionMethod:
quelle
Ein out-Parameter ist ideal, wenn nur wenige Werte zurückgegeben werden müssen. Wenn Sie jedoch auf 4, 5, 6 oder mehr Werte stoßen, die zurückgegeben werden müssen, kann dies unhandlich werden. Eine weitere Option zum Zurückgeben mehrerer Werte besteht darin, eine benutzerdefinierte Klasse / Struktur zu erstellen und zurückzugeben oder ein Tupel zu verwenden, um alle Werte zu verpacken, die von einer Methode zurückgegeben werden müssen.
Die erste Option, bei der eine Klasse / Struktur zum Zurückgeben der Werte verwendet wird, ist unkompliziert. Erstellen Sie einfach den Typ (in diesem Beispiel ist es eine Struktur) wie folgt:
Die zweite Option, ein Tupel zu verwenden, ist eine noch elegantere Lösung als die Verwendung eines benutzerdefinierten Objekts. Es kann ein Tupel erstellt werden, das eine beliebige Anzahl von Werten unterschiedlichen Typs enthält. Darüber hinaus sind die Daten, die Sie im Tupel speichern, unveränderlich. Sobald Sie die Daten über den Konstruktor oder die statische Create-Methode zum Tupel hinzugefügt haben, können diese Daten nicht mehr geändert werden. Tupel können bis zu acht separate Werte akzeptieren. Wenn Sie mehr als acht Werte zurückgeben müssen, müssen Sie die spezielle Tupelklasse verwenden: Tupelklasse Wenn Sie ein Tupel mit mehr als acht Werten erstellen, können Sie die statische Create-Methode nicht verwenden. Sie müssen stattdessen den Konstruktor der Klasse verwenden. So würden Sie ein Tupel mit 10 ganzzahligen Werten erstellen:
Natürlich können Sie am Ende jedes eingebetteten Tupels weitere Tupel hinzufügen und so ein beliebiges Tupel erstellen.
quelle
Nur für das Prototyping - Tupel sind bedeutungslos. Es ist bequem, sie zu benutzen, aber es ist nur eine Abkürzung! Für Prototypen - gut. Löschen Sie diesen Code später unbedingt.
Es ist leicht zu schreiben, schwer zu lesen. Es hat keine sichtbaren Vorteile gegenüber Klassen, inneren Klassen, anonymen Klassen usw.
quelle
Nun, ich habe drei Möglichkeiten ausprobiert, um das gleiche Problem in C # 7 zu lösen, und ich habe einen Anwendungsfall für Tuples gefunden.
Das Arbeiten mit dynamischen Daten in Webprojekten kann beim Mapping usw. manchmal schwierig sein.
Ich mag die Art und Weise, wie das Tupel nur automatisch auf item1, item2, itemN abgebildet wird, was mir robuster erscheint als die Verwendung von Array-Indizes, bei denen Sie möglicherweise auf ein Element außerhalb des Indexes stoßen, oder die Verwendung des anonymen Typs, bei dem Sie möglicherweise einen Eigenschaftsnamen falsch schreiben.
Es fühlt sich so an, als ob ein DTO nur mit einem Tupel kostenlos erstellt wurde, und ich kann mit itemN auf alle Eigenschaften zugreifen, was eher wie statische Eingabe aussieht, ohne dass zu diesem Zweck ein separates DTO erstellt werden muss.
quelle