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.

Amitabh
quelle
13
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.

Tanascius
quelle
5
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:

var forex = new Dictionary<Tuple<string, string>, decimal>();
forex.Add(Tuple.Create("USD", "EUR"), 0.74850m); // 1 USD = 0.74850 EUR
forex.Add(Tuple.Create("USD", "GBP"), 0.64128m);
forex.Add(Tuple.Create("EUR", "USD"), 1.33635m);
forex.Add(Tuple.Create("EUR", "GBP"), 0.85677m);
forex.Add(Tuple.Create("GBP", "USD"), 1.55938m);
forex.Add(Tuple.Create("GBP", "EUR"), 1.16717m);
forex.Add(Tuple.Create("USD", "USD"), 1.00000m);
forex.Add(Tuple.Create("EUR", "EUR"), 1.00000m);
forex.Add(Tuple.Create("GBP", "GBP"), 1.00000m);

decimal result;
result = 35.0m * forex[Tuple.Create("USD", "EUR")]; // USD 35.00 = EUR 26.20
result = 35.0m * forex[Tuple.Create("EUR", "GBP")]; // EUR 35.00 = GBP 29.99
result = 35.0m * forex[Tuple.Create("GBP", "USD")]; // GBP 35.00 = USD 54.58
MarioVW
quelle
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 .

Hans Passant
quelle
23

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.

public static void Main(string[] args)
{
    int userId = 0;
    Tuple<string, string> userData = GetUserData(userId);
}

public static Tuple<string, string> GetUserData(int userId)
{
    return new Tuple<string, string>("Hello", "World");
}
Tejs
quelle
10
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.
Joel Mueller
23

Ich habe ein Tupel verwendet, um Problem 11 von Project Euler zu lösen :

class Grid
{
    public static int[,] Cells = { { 08, 02, 22, // whole grid omitted

    public static IEnumerable<Tuple<int, int, int, int>> ToList()
    {
        // code converts grid to enumeration every possible set of 4 per rules
        // code omitted
    }
}

Jetzt kann ich das ganze Problem lösen mit:

class Program
{
    static void Main(string[] args)
    {
        int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
        Console.WriteLine("Maximum product is {0}", product);
    }
}

Ich hätte einen benutzerdefinierten Typ dafür verwenden können, aber er hätte genau wie Tupel ausgesehen .

Craig Stuntz
quelle
16

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 time
var 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:

static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
    Tuple<T, State> res;
    while ((res = f(seed)) != null)
    {
        yield return res.Item1;
        seed = res.Item2;
    }
}

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, 8
var evens =
    Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
    .ToList();

// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var 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.

Julia
quelle
4
+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):

    int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
    {
        return Tuple.CombineHashCodes(comparer.GetHashCode(this.m_Item1), comparer.GetHashCode(this.m_Item2), comparer.GetHashCode(this.m_Item3));
    }
Notoriousxl
quelle
7

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!):

Task.Factory.StartNew(() => data.RetrieveServerNames())
    .ContinueWith(antecedent1 =>
        {
            if (!antecedent1.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent1.Result);
                Task.Factory.StartNew(() => data.RetrieveLogNames())
                    .ContinueWith(antecedent2 =>
                        {
                            if (antecedent2.IsFaulted)
                            {
                                LogNames = KeepExistingFilter(LogNames, antecedent2.Result);
                                Task.Factory.StartNew(() => data.RetrieveEntryTypes())
                                    .ContinueWith(antecedent3 =>
                                        {
                                            if (!antecedent3.IsFaulted)
                                            {
                                                EntryTypes = KeepExistingFilter(EntryTypes, antecedent3.Result);
                                            }
                                        });
                            }
                        });
            }
        });

Mit Tupel

Task.Factory.StartNew(() =>
    {
        List<string> serverNames = data.RetrieveServerNames();
        List<string> logNames = data.RetrieveLogNames();
        List<string> entryTypes = data.RetrieveEntryTypes();
        return Tuple.Create(serverNames, logNames, entryTypes);
    }).ContinueWith(antecedent =>
        {
            if (!antecedent.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent.Result.Item1);
                LogNames = KeepExistingFilter(LogNames, antecedent.Result.Item2);
                EntryTypes = KeepExistingFilter(EntryTypes, antecedent.Result.Item3);
            }
        });

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.

AndyClaw
quelle
5

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.

Mant101
quelle
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:

Mercedes, Seattle
Mustang, Denver
Mercedes, Seattle
Porsche, Seattle
Tesla, Seattle
Mercedes, Seattle

Sie möchten die Anzahl für jedes Auto pro Stadt aggregieren:

Mercedes, Seattle [3]
Mustang, Denver [1]
Porsche, Seattle [1]
Tesla, Seattle [1]

Dazu erstellen Sie eine Dictionary. Sie haben einige Möglichkeiten:

  1. Erstellen Sie eine Dictionary<string, Dictionary<string, int>>.
  2. Erstellen Sie eine Dictionary<CarAndCity, int>.
  3. 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.

John Kurlak
quelle
4

Ein paar Beispiele aus meinem Kopf:

  • Eine X- und Y-Position (und Z, wenn Sie möchten)
  • eine Breite und Höhe
  • Alles, was im Laufe der Zeit gemessen wurde

Zum Beispiel möchten Sie System.Drawing nicht in eine Webanwendung aufnehmen, nur um Point / PointF und Size / SizeF zu verwenden.

James Westgate
quelle
2
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 ?

Mr. Pumpkin
quelle
1

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

private string MyMethod(out object)

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.

Sidjames
quelle
1

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 list
 var rolesWithUsers = (from role in roles
                       select new Tuple<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 collection
 var tempResult = rolesWithUsers.ToList();
 tempResult.Add(new Tuple<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 JSON
 return new JavaScriptSerializer().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.

Alex
quelle
1

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 = await GetUserDetails(userId);
Console.WriteLine("Username : {0}", userDetails.Item1);
Console.WriteLine("User Region Id : {0}", userDetails.Item2);
...
...

private async Tuple<string,int> GetUserDetails(int userId)
{
    return new Tuple<string,int>("Amogh",105);
    // Note that I can also use the existing helper method (Tuple.Create).
}

Lesen Sie hier mehr über Tuple . Hoffe das hilft.

Amogh Natu
quelle
Ich
gehe
0

Ä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 = new Tuple<Customer, List<Address>>(mainCustomer, new List<Address> {mainCustomerAddress}).ToCustomerDetails();

ExtensionMethod:

public static CustomerDetails ToCustomerDetails(this Tuple<Website.Customer, List<Website.Address>> customerAndAddress)
    {
        var mainAddress = customerAndAddress.Item2 != null ? customerAndAddress.Item2.SingleOrDefault(o => o.Type == "Main") : null;
        var customerDetails = new CustomerDetails
        {
            FirstName = customerAndAddress.Item1.Name,
            LastName = customerAndAddress.Item1.Surname,
            Title = customerAndAddress.Item1.Title,
            Dob = customerAndAddress.Item1.Dob,
            EmailAddress = customerAndAddress.Item1.Email,
            Gender = customerAndAddress.Item1.Gender,
            PrimaryPhoneNo = string.Format("{0}", customerAndAddress.Item1.Phone)
        };

        if (mainAddress != null)
        {
            customerDetails.AddressLine1 =
                !string.IsNullOrWhiteSpace(mainAddress.HouseName)
                    ? mainAddress.HouseName
                    : mainAddress.HouseNumber;
            customerDetails.AddressLine2 =
                !string.IsNullOrWhiteSpace(mainAddress.Street)
                    ? mainAddress.Street
                    : null;
            customerDetails.AddressLine3 =
                !string.IsNullOrWhiteSpace(mainAddress.Town) ? mainAddress.Town : null;
            customerDetails.AddressLine4 =
                !string.IsNullOrWhiteSpace(mainAddress.County)
                    ? mainAddress.County
                    : null;
            customerDetails.PostCode = mainAddress.PostCode;
        }
...
        return customerDetails;
    }
Matas Vaitkevicius
quelle
0

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:

public struct Dimensions
{
public int Height;
public int Width;
public int Depth;
}

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 = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>> (
1, 2, 3, 4, 5, 6, 7, new Tuple<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.

Yashwanth Chowdary Kata
quelle
0

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.

Hase1985
quelle
0

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.

using System;

namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            var tuple = GetTuple();
            Console.WriteLine(tuple.Item1);
            Console.WriteLine(tuple.Item2);
            Console.WriteLine(tuple.Item3);
            Console.WriteLine(tuple);

            Console.WriteLine("---");

            var dyn = GetDynamic();
            Console.WriteLine(dyn.First);
            Console.WriteLine(dyn.Last);
            Console.WriteLine(dyn.Age);
            Console.WriteLine(dyn);

            Console.WriteLine("---");

            var arr = GetArray();
            Console.WriteLine(arr[0]);
            Console.WriteLine(arr[1]);
            Console.WriteLine(arr[2]);
            Console.WriteLine(arr);

            Console.Read();

            (string, string, int) GetTuple()
            {
                return ("John", "Connor", 1);
            }

            dynamic GetDynamic()
            {
                return new { First = "John", Last = "Connor", Age = 1 };
            }

            dynamic[] GetArray()
            {
                return new dynamic[] { "John", "Connor", 1 };
            }
        }
    }
}
ozzy432836
quelle