Multiple Rückgabewerte mit Tupeln in C#

Multiple Rückgabewerte mit Tupeln in C#

Noel Hödtke | Softwareentwickler | 26.03.2024

Einleitung

In modernen Anwendungen kommt es häufiger vor, dass Daten aus verschiedenen Quellen verarbeitet werden müssen.

Seit C# 7 gibt es die Möglichkeit dieses Vorhaben mit Hilfe von Tupeln zu vereinfachen.

Durch Tupel ist es möglich, eine Gruppierung von Werten zu erstellen, die normalerweise aus verschiedenen Objekten oder Datentypen geholt werden müssten.

In diesem Artikel werden die Funktionen von Tupeln durch Beispiele verdeutlicht, sowie Vor- und Nachteile beleuchtet.

Allgemeines zu Tupeln

Tupel sind Datenstrukturen, die über eine vordefinierte Anzahl von Elementen verfügen.

Im Gegensatz zu anderen Strukturen wie Listen oder Arrays, können Tupel unterschiedlich aufgebaut werden und über mehrere Datentypen verfügen.

Erstellen von Tupeln:

Um ein Tupel zu erstellen, müssen erst die Werte in Klammern oder über die Tupel-Kalsse definiert werden.

 

//Erstellen über definition der Werte
 (int, string) contact = (1, "Max Mustermann");
 Console.WriteLine($"{contact.Item2} hat die ID {contact.Item1}");


 //Erstellen über die Tuple Klasse
 Tuple<int, string> secondContact = new Tuple<int, string>(1, "Max Mustermann");

//Bennung der Werte
var contact3 = (ID: 1, Name: "Max Mustermann");
Console.WriteLine($"{contact3.Name} hat die ID {contact3.ID}");
//Ausgabe: Max Mustermann hat die ID 1

 

Alternativ ist es auch möglich Tupel direkt über eine Methode zu deklarieren.

private static (int, string) GetPosition()
{
    return (1, "position");
}
private static (int position, string name) GetPositionV2()
{
    return (1, "position");
}
var positon = GetPosition();
var secondPosition = GetPositionV2();

 

Tupel können über beliebig viele Werte verfügen.

//Tupel mit mehreren Werten
 var adress = (Street: "Musterstraße", Number: 1, Zip: 12345, City: "Musterstadt");
 Console.WriteLine($"{adress.Street} {adress.Number}, {adress.Zip} {adress.City}");

Praxisnahes Beispiel:

Ein Kunde möchte, dass für jeden Kontakt in unserer Anwendung die zugehörigen Bilder, aus einem Storage, geladen werden um diese später im Frontend auszugeben.

Hierfür brauchen wir die Zuordnung von der ID und der Liste mit Bildern des Kontaktes.

In unserem AssetService können wir hierfür eine Methode definieren, die uns eine KontaktID mit den zugehörigen Bildern in einem Tupel zurück liefert.

namespace MultipleReturns
{   
    public interface IAssetService
    {
        List<Tuple<int, byte[]>> GetAssignedAssets(List<int> contactIDs);
    }
}
namespace MultipleReturns
{
    /// <summary>
    /// Service zum laden der Assets von Kontakten
    /// </summary>
    public class AssetService : IAssetService
    {
        public List<Tuple<int, byte[]>> GetAssignedAssets(List<int> contactIDs)
        {
            var result = new List<Tuple<int, byte[]>>();
            // die Assets für die angegebenen Kontakte laden
            // die Assets zu der Liste mit den Ergebnissen hinzufügen

            return result;
        }
    }
}

 

 

Vorteile von Tupeln:

Vereinfachung

Durch Tupel können mehrere Werte einfach gruppiert werden, ohne dass eine separate Klasse oder Struktur definiert werden muss. Dies kann den Code, bei kleineren oder temporären Datensammlungen, vereinfachen.

Verbesserte Lesbarkeit (bei benannten Tupeln)

Mit der Einführung von benannten Tupeln in C# 7.0 kann Code lesbarer gemacht werden, indem den Tupel-Elementen Namen zugewiesen werden. Dies verbessert die Verständlichkeit des Codes, insbesondere im Kontext der Daten, die das Tupel repräsentiert.

Unterstützung für multiple Rückgabewerte

Tupel bieten eine saubere und typsichere Möglichkeit, mehrere Werte aus einer Methode zurückzugeben, ohne auf Out-Parameter oder das Definieren einer zusätzlichen Klasse zurückgreifen zu müssen.

Vereinfachung von Methodensignaturen

Durch die Verwendung von Tupeln können Methodensignaturen vereinfacht werden, indem mehrere Ausgabeparameter in einem einzigen Rückgabetyp zusammengefasst werden. Dies reduziert die Komplexität von Methodenaufrufen und macht den Code übersichtlicher.

Nachteile von Tupeln:

Verständlichkeit

Der übermäßige Einsatz von Tupeln, kann den Code schwer verständlich machen, da die Bedeutung jedes Tupel-Elements ohne ausreichende Dokumentation nicht immer klar ist.

Wartbarkeit 

Änderungen an der Struktur eines Tupels können sich auf viele Bereiche des Codes auswirken, insbesondere wenn das Tupel als Rückgabetyp einer Methode verwendet wird. Das Hinzufügen, Entfernen oder Ändern von Elementen kann eine Fülle von Änderungen erforderlich machen.

Wiederverwendbarkeit 

Tupel fördern möglicherweise nicht die Wiederverwendbarkeit von Code im Vergleich zu Klassen oder Strukturen, da Tupel tendenziell spezifisch für den Kontext sind, in dem sie verwendet werden. Für allgemeinere Datenstrukturen, die in verschiedenen Teilen einer Anwendung wiederverwendet werden können, sind Klassen oder Strukturen oft die bessere Wahl.

Performance

Obwohl Tupel in vielen Szenarien effizient sind, kann die Erstellung großer Mengen von Tupeln oder die häufige Erstellung und Zerstörung von Tupeln in Leistungskritischen Anwendungen zu einem erhöhten Speicherverbrauch und zu einer höheren Last auf dem Garbage Collector führen, insbesondere im Vergleich zu einfachen Werttypen oder wiederverwendeten Objekten.

Fazit

Tupel sind vor allem nützlich für die Rückgabe von mehreren Werten aus einer Methode oder als temporäre Verknüpfung von Werten. Wenn ein Tupel an vielen Stellen verwendet werden muss, würde ich aufgrund der Wartbarkeit eher dazu raten eine Klasse zu erstellen. 

GitHub-Beispiel: https://github.com/NoelJanH/MultipleReturns

 

Noel Hödtke | Softwareentwickler | 26.03.2024

Sie suchen einen Software Anbieter?
Sprechen Sie uns an