Bessere Benennung in Tupelklassen als "Item1", "Item2"


204

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.)


1
Du musst deine eigenen rollen - Tupleist sehr allgemein gehalten, das ist alles, was du bekommst
BrokenGlass

NEIN, das können Sie nicht. Weitere Informationen finden Sie
Enigma State

1
Ich möchte sagen, dass die Verwendung eines Tupels als öffentlich zugänglicher Datentyp für Ihre API möglicherweise nicht empfohlen wird. Ich benutze Tuple normalerweise für kurzlebige interne Dinge, nicht als Rückgabewert einer API.
Mike Burdick


4
Es ist in der Arbeitsliste von C # 7 Siehe github.com/dotnet/roslyn/issues/347
Philip Ding

Antworten:


277

In C # 7.0 (Visual Studio 2017) gibt es dafür eine neue Konstruktion:

(string first, string middle, string last) LookupName(long id)

68
Die Syntax lautet List<(int first, int second)>. Ich musste das System.ValueTuple-Paket von NuGet herunterladen, damit es in Visual Studio 2017 funktioniert.
Matt Davis

14
Um den Wert zu erstellenreturn (first: first, middle: middle, last: last);
Fiat

4
oder nur: return (first, middle, last);in .NET 4.7.1 (nicht sicher für 4.7.0)
watbywbarif

1
Um es zu verwenden, müssen Sie das System.ValueTuple Nuget-Paket hinzufügen
Alex G

11
Es sollte beachtet werden, dass C # 7 ValueTuple, obwohl normalerweise großartig, ein veränderbarer Werttyp (struct) ist, während Tuplees ein unveränderlicher Referenztyp (Klasse) ist. Soweit ich weiß, gibt es keine Möglichkeit, einen Referenztyp Tuplemit benutzerfreundlichen Artikelnamen zu erhalten.
dx_over_dt

51

Bis C # 7.0 gab es keine Möglichkeit, dies zu tun, ohne Ihren eigenen Typ zu definieren.


13
Ich kann nicht glauben, dass diese Antwort mit einer Punktzahl von 40 akzeptiert wird. Sie hätten zumindest zeigen können, wie eine Klasse mit einem geeigneten Konstruktor dies ersetzen kann.
Bytecode77

1
@ Bytecode77 Nun, ziemlich bald wird diese Antwort falsch sein: github.com/dotnet/roslyn/issues/347
MarkPflug

Ich habe diese Vorschläge für Sprachfeste gesehen. Bis jetzt ist eine Klasse die einzig richtige Lösung für komplexere Datentypen. Warum würden Sie wollen Tupeln gewaltsam verwenden , egal was (andere Antworten sehen)
bytecode77

3
Nach der Veröffentlichung von C # 7 ist dies möglich: msdn.microsoft.com/en-us/magazine/mt595758.aspx
Burak Karakuş

11
Das Q 'hat c # 4 als Tag, und obwohl diese Antwort kurz ist, ist sie immer noch korrekt.
Steve Drake

33

Hier ist eine übermäßig komplizierte Version dessen, was Sie fragen:

class MyTuple : Tuple<int, int>
{
    public MyTuple(int one, int two)
        :base(one, two)
    {

    }

    public int OrderGroupId { get{ return this.Item1; } }
    public int OrderTypeId { get{ return this.Item2; } }

}

Warum nicht einfach eine Klasse machen?


2
Wäre Struktur in diesem Fall besser als Klasse?
Deathrace

5
Der kleine Vorteil, den ich dabei sehe, ist, dass der Operator equals automatisch implementiert wird und überprüft wird, ob 2 Instanzen gleich sind, wenn alle Elemente gleich sind.
JSoet

8
Ein weiterer Nachteil dieses Ansatzes ist, dass Item1 und Item2 immer noch öffentliche Objekte auf MyTuple
RJFalconer sind.

3
@deathrace Tupel selbst sind Klassen. Wenn Sie also direkt von ihnen erben möchten, können Tuple<T, T2>Sie keine Struktur sein.
Chakrava

3
Ich kann mich irren, aber ich benutze meistens Tupel, wo immer ich ein Objekt zurückgeben möchte, aber keine bestimmte Klasse definieren möchte.
Jay

12

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.

class Program
{
    static void Main(string[] args)
    {
        dynamic employee, manager;

        employee = new ExpandoObject();
        employee.Name = "John Smith";
        employee.Age = 33;

        manager = new ExpandoObject();
        manager.Name = "Allison Brown";
        manager.Age = 42;
        manager.TeamSize = 10;

        WritePerson(manager);
        WritePerson(employee);
    }
    private static void WritePerson(dynamic person)
    {
        Console.WriteLine("{0} is {1} years old.",
                          person.Name, person.Age);
        // The following statement causes an exception
        // if you pass the employee object.
        // Console.WriteLine("Manages {0} people", person.TeamSize);
    }
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.

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.

var MyStuff = new
    {
        PropertyName1 = 10,
        PropertyName2 = "string data",
        PropertyName3 = new ComplexType()
    };

10

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, Item2und so weiter.

Benennen der Eigenschaften von Tupel-Literalen :

var myDetails = (MyName: "RBT_Yoga", MyAge: 22, MyFavoriteFood: "Dosa");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");

Die Ausgabe auf der Konsole:

Name - RBT_Yoga, Alter - 22, Leidenschaft - Dosa

Rückgabe von Tupel (mit benannten Eigenschaften) von einer Methode :

static void Main(string[] args)
{
    var empInfo = GetEmpInfo();
    Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}

static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
    //This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
    return ("Rasik", "Bihari", "Rasik-PC", 1000);
}

Die Ausgabe auf der Konsole:

Mitarbeiterdetails: Rasik, Bihari, Rasik-PC, 1000

Erstellen einer Liste von Tupeln mit benannten Eigenschaften

var tupleList = new List<(int Index, string Name)>
{
    (1, "cow"),
    (5, "chickens"),
    (1, "airplane")
};

foreach (var tuple in tupleList)
    Console.WriteLine($"{tuple.Index} - {tuple.Name}");

Ausgabe auf der Konsole:

1 - Kuh 5 - Hühner 1 - Flugzeug

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 .


3

MichaelMocko Beantwortet ist großartig,

aber ich möchte ein paar Dinge hinzufügen, die ich herausfinden musste

(string first, string middle, string last) LookupName(long id)

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



2

Wenn die Arten Ihrer Artikel alle unterschiedlich sind, habe ich eine Klasse erstellt, um sie intuitiver zu gestalten.

Die Verwendung dieser Klasse:

var t = TypedTuple.Create("hello", 1, new MyClass());
var s = t.Get<string>();
var i = t.Get<int>();
var c = t.Get<MyClass>();

Quellcode:

public static class TypedTuple
{
    public static TypedTuple<T1> Create<T1>(T1 t1)
    {
        return new TypedTuple<T1>(t1);
    }

    public static TypedTuple<T1, T2> Create<T1, T2>(T1 t1, T2 t2)
    {
        return new TypedTuple<T1, T2>(t1, t2);
    }

    public static TypedTuple<T1, T2, T3> Create<T1, T2, T3>(T1 t1, T2 t2, T3 t3)
    {
        return new TypedTuple<T1, T2, T3>(t1, t2, t3);
    }

    public static TypedTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4)
    {
        return new TypedTuple<T1, T2, T3, T4>(t1, t2, t3, t4);
    }

    public static TypedTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
    {
        return new TypedTuple<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8);
    }

}

public class TypedTuple<T>
{
    protected Dictionary<Type, object> items = new Dictionary<Type, object>();

    public TypedTuple(T item1)
    {
        Item1 = item1;
    }

    public TSource Get<TSource>()
    {
        object value;
        if (this.items.TryGetValue(typeof(TSource), out value))
        {
            return (TSource)value;
        }
        else
            return default(TSource);
    }

    private T item1;
    public T Item1 { get { return this.item1; } set { this.item1 = value; this.items[typeof(T)] = value; } }
}

public class TypedTuple<T1, T2> : TypedTuple<T1>
{
    public TypedTuple(T1 item1, T2 item2)
        : base(item1)
    {
        Item2 = item2;
    }

    private T2 item2;
    public T2 Item2 { get { return this.item2; } set { this.item2 = value; this.items[typeof(T2)] = value; } }
}

public class TypedTuple<T1, T2, T3> : TypedTuple<T1, T2>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3)
        : base(item1, item2)
    {
        Item3 = item3;
    }

    private T3 item3;
    public T3 Item3 { get { return this.item3; } set { this.item3 = value; this.items[typeof(T3)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4> : TypedTuple<T1, T2, T3>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4)
        : base(item1, item2, item3)
    {
        Item4 = item4;
    }

    private T4 item4;
    public T4 Item4 { get { return this.item4; } set { this.item4 = value; this.items[typeof(T4)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5> : TypedTuple<T1, T2, T3, T4>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
        : base(item1, item2, item3, item4)
    {
        Item5 = item5;
    }

    private T5 item5;
    public T5 Item5 { get { return this.item5; } set { this.item5 = value; this.items[typeof(T5)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6> : TypedTuple<T1, T2, T3, T4, T5>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
        : base(item1, item2, item3, item4, item5)
    {
        Item6 = item6;
    }

    private T6 item6;
    public T6 Item6 { get { return this.item6; } set { this.item6 = value; this.items[typeof(T6)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6, T7> : TypedTuple<T1, T2, T3, T4, T5, T6>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
        : base(item1, item2, item3, item4, item5, item6)
    {
        Item7 = item7;
    }

    private T7 item7;
    public T7 Item7 { get { return this.item7; } set { this.item7 = value; this.items[typeof(T7)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> : TypedTuple<T1, T2, T3, T4, T5, T6, T7>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
        : base(item1, item2, item3, item4, item5, item6, item7)
    {
        Item8 = item8;
    }

    private T8 item8;
    public T8 Item8 { get { return this.item8; } set { this.item8 = value; this.items[typeof(T8)] = value; } }
}

4
Dies scheint eine Menge Arbeit für wenig bis gar keine Auszahlung zu sein. Es hat eine unintuitive Einschränkung (keine doppelten Typen), und ich finde die Idee, einen Wert nur anhand seines Typs abzurufen, unglaublich unintuitiv und kann mir keinen praktischen Anwendungsfall dafür vorstellen. Dies entspricht der Erstellung einer Datentabelle für Mitarbeiter, der Entscheidung, Mitarbeiter anhand ihres Vornamens abzurufen (im Gegensatz zu einem eindeutigen Schlüssel) und der anschließenden Anforderung, dass alle Mitarbeiter unterschiedliche Vornamen haben müssen. Dies ist keine Lösung für ein Problem, sondern eine Lösung auf Kosten der Erstellung eines zusätzlichen Problems.
Flater

Und möge Gott deiner Seele gnädig sein.
Jamie M.

1

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.

Tuple<ApiResource, JSendResponseStatus> result = await SendApiRequest();
ApiResource apiResource = result.Item1;
JSendResponseStatus jSendStatus = result.Item2;

0

Ich denke, ich würde eine Klasse erstellen, aber eine andere Alternative sind Ausgabeparameter.

public void GetOrderRelatedIds(out int OrderGroupId, out int OrderTypeId, out int OrderSubTypeId, out int OrderRequirementId)

Da Ihr Tupel nur Ganzzahlen enthält, können Sie es mit a darstellen Dictionary<string,int>

var orderIds = new Dictionary<string, int> {
    {"OrderGroupId", 1},
    {"OrderTypeId", 2},
    {"OrderSubTypeId", 3},
    {"OrderRequirementId", 4}.
};

aber das empfehle ich auch nicht.


0

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

  • Ein benutzerdefinierter Datentyp
    • ohne weitere Funktionalität. Getter und Setter können auch mit Code erweitert werden, indem private Mitglieder mit dem Namensmuster "_orderGroupId" abgerufen / festgelegt werden und gleichzeitig Funktionscode ausgeführt wird.
  • Einschließlich Konstruktoren. Sie können auch nur einen Konstruktor einschließen, wenn alle Eigenschaften obligatorisch sind.
  • Wenn Sie alle Konstruktoren verwenden möchten, ist das Sprudeln wie dieses das richtige Muster, um doppelten Code zu vermeiden.

public class OrderRelatedIds
{
    public int OrderGroupId { get; set; }
    public int OrderTypeId { get; set; }
    public int OrderSubTypeId { get; set; }
    public int OrderRequirementId { get; set; }

    public OrderRelatedIds()
    {
    }
    public OrderRelatedIds(int orderGroupId)
        : this()
    {
        OrderGroupId = orderGroupId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId)
        : this(orderGroupId)
    {
        OrderTypeId = orderTypeId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId)
        : this(orderGroupId, orderTypeId)
    {
        OrderSubTypeId = orderSubTypeId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId, int orderRequirementId)
        : this(orderGroupId, orderTypeId, orderSubTypeId)
    {
        OrderRequirementId = orderRequirementId;
    }
}

Oder, wenn Sie es wirklich einfach wollen: Sie können auch Typinitialisierer verwenden:

OrderRelatedIds orders = new OrderRelatedIds
{
    OrderGroupId = 1,
    OrderTypeId = 2,
    OrderSubTypeId = 3,
    OrderRequirementId = 4
};

public class OrderRelatedIds
{
    public int OrderGroupId;
    public int OrderTypeId;
    public int OrderSubTypeId;
    public int OrderRequirementId;
}

0

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

 helloworld("Hi1,Hi2");

/// <summary>
/// Return hello = Item1 and world Item2
/// </summary>
/// <param name="input">string to split</param>
/// <returns></returns>
private static Tuple<bool, bool> helloworld(string input)
{
    bool hello = false;
    bool world = false;
    foreach (var hw in input.Split(','))
    {
        switch (hw)
        {
            case "Hi1":
                hello= true;
                break;
            case "Hi2":
                world= true;
                break;
        }

    }
    return new Tuple<bool, bool>(hello, world);
}

0

Nur um @MichaelMocko Antwort hinzuzufügen. Tupel haben im Moment ein paar Fallstricke:

Sie können sie nicht in EF-Ausdrucksbäumen verwenden

Beispiel:

public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        // Selecting as Tuple
        .Select(person => (person.Name, person.Surname))
        .First();
}

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:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => new { person.Name, person.Surname })
        .ToList()
        .Select(person => (person.Name, person.Surname))
        .First();
}

Eine weitere Option ist die Verwendung von ValueTuple.Create:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname))
        .First();
}

Verweise:

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:

public static IQueryable<(string name, string surname)> GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname));
}

// This won't work
ctx.GetPersonName(id).Select((name, surname) => { return name + surname; })

// But this will
ctx.GetPersonName(id).Select(t => { return t.name + t.surname; })

Verweise:

Sie werden nicht gut serialisiert

using System;
using Newtonsoft.Json;

public class Program
{
    public static void Main() {
        var me = (age: 21, favoriteFood: "Custard");
        string json = JsonConvert.SerializeObject(me);

        // Will output {"Item1":21,"Item2":"Custard"}
        Console.WriteLine(json); 
    }
}

Tupelfeldnamen sind nur zur Kompilierungszeit verfügbar und werden zur Laufzeit vollständig gelöscht.

Verweise:


-1

Sie können eine Klasse schreiben, die das Tupel enthält.

Sie müssen die Funktionen Equals und GetHashCode überschreiben

und die Operatoren == und! =.

class Program
{
    public class MyTuple
    {
        private Tuple<int, int> t;

        public MyTuple(int a, int b)
        {
            t = new Tuple<int, int>(a, b);
        }

        public int A
        {
            get
            {
                return t.Item1;
            }
        }

        public int B
        {
            get
            {
                return t.Item2;
            }
        }

        public override bool Equals(object obj)
        {
            return t.Equals(((MyTuple)obj).t);
        }

        public override int GetHashCode()
        {
            return t.GetHashCode();
        }

        public static bool operator ==(MyTuple m1, MyTuple m2)
        {
            return m1.Equals(m2);
        }

        public static bool operator !=(MyTuple m1, MyTuple m2)
        {
            return !m1.Equals(m2);
        }
    }

    static void Main(string[] args)
    {
        var v1 = new MyTuple(1, 2);
        var v2 = new MyTuple(1, 2);

        Console.WriteLine(v1 == v2);

        Dictionary<MyTuple, int> d = new Dictionary<MyTuple, int>();
        d.Add(v1, 1);

        Console.WriteLine(d.ContainsKey(v2));
    }
}

wird zurückkehren:

Wahr

Wahr


2
Wenn Sie bereits eine Klasse für diesen Datentyp implementiert haben, warum deklarieren Sie ein Tupel für die zugrunde liegenden Daten anstatt nur für Eigenschaften?
Bytecode77

Ich möchte das Tupel-Attribut verwenden, das es nach Wert in der Equals-Funktion berechnet
ss

Das kann ein Bonus sein. Andererseits haben Sie im Grunde genommen eine Klasse mit Eigenschaften erstellt, die von Item1 bis ItemX reichen. Ich würde die richtige Benennung und mehr Code in Equals () anstelle der Verwendung eines Tupels wählen.
Bytecode77

-1

Beispiel für ein C # 7-Tupel

var tuple = TupleExample(key, value);

     private (string key1, long value1) ValidateAPIKeyOwnerId(string key, string value)
            {
                return (key, value);
            }
      if (!string.IsNullOrEmpty(tuple.key1) && tuple.value1 > 0)
          {
                    //your code

                }     
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.