375 Stimmen

Wie lässt sich eine Liste von Tupeln einfach initialisieren?

Ich liebe Tupel . Sie ermöglichen es Ihnen, relevante Informationen schnell zu gruppieren, ohne eine Struktur oder Klasse dafür schreiben zu müssen. Dies ist sehr nützlich beim Refactoring von sehr lokalisiertem Code.

Die Initialisierung einer Liste von ihnen scheint jedoch etwas überflüssig zu sein.

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

Gibt es nicht einen besseren Weg? Ich würde gerne eine Lösung nach dem Vorbild der Wörterbuch-Initialisierer .

Dictionary<int, string> students = new Dictionary<int, string>()
{
    { 111, "bleh" },
    { 112, "bloeh" },
    { 113, "blah" }
};

Können wir nicht eine ähnliche Syntax verwenden?

444voto

toddmo Punkte 18450

Mit c# 7.0 können Sie dies tun:

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

Wenn Sie keine List , sondern nur ein Array, können Sie tun:

  var tupleList = new(int, string)[]
  {
      (1, "cow"),
      (5, "chickens"),
      (1, "airplane")
  };

Und wenn Sie "Item1" und "Item2" nicht mögen, können Sie das tun:

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

oder für ein Array:

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

was Sie tun können: tupleList[0].Index y tupleList[0].Name

Framework 4.6.2 und darunter

Sie müssen Folgendes installieren System.ValueTuple aus dem Nuget-Paketmanager.

Framework 4.7 und höher

Sie ist in den Rahmen integriert. Do nicht installieren System.ValueTuple . In der Tat, entfernen Sie es und löschen Sie es aus dem Verzeichnis bin.

Anmerkung: Im wirklichen Leben könnte ich mich nicht zwischen Kuh, Hühnern und Flugzeug entscheiden. Ich wäre wirklich hin- und hergerissen.

235voto

Steven Jeuris Punkte 17118

Ja! Dies ist möglich .

があります。 { } Syntax des Sammlungsinitialisierers funktioniert bei jeder IEnumerable Typ, der eine hinzufügen Methode mit der richtigen Anzahl von Argumenten. Ohne sich darum zu kümmern, wie das im Detail funktioniert, bedeutet das, dass Sie einfach erweitern von Liste<T> fügen Sie eine benutzerdefinierte Add-Methode zur Initialisierung von yo T und Sie sind fertig!

public class TupleList<T1, T2> : List<Tuple<T1, T2>>
{
    public void Add( T1 item, T2 item2 )
    {
        Add( new Tuple<T1, T2>( item, item2 ) );
    }
}

Damit können Sie Folgendes tun:

var groceryList = new TupleList<int, string>
{
    { 1, "kiwi" },
    { 5, "apples" },
    { 3, "potatoes" },
    { 1, "tomato" }
};

89voto

Jeff Mercado Punkte 120818

C# 6 bietet dafür eine neue Funktion: die Erweiterung Add methods. Dies war schon immer für VB.net möglich, ist aber jetzt auch in C# verfügbar.

Jetzt müssen Sie nicht mehr Add() Methoden nicht direkt in Ihre Klassen aufnehmen, können Sie sie als Erweiterungsmethoden implementieren. Bei der Erweiterung eines beliebigen aufzählbaren Typs mit einer Add() Methode können Sie sie in Initialisierungsausdrücken für Sammlungen verwenden. Sie müssen also nicht mehr explizit von Listen ableiten ( wie in einer anderen Antwort erwähnt ), können Sie es einfach erweitern.

public static class TupleListExtensions
{
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
            T1 item1, T2 item2)
    {
        list.Add(Tuple.Create(item1, item2));
    }

    public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
            T1 item1, T2 item2, T3 item3)
    {
        list.Add(Tuple.Create(item1, item2, item3));
    }

    // and so on...
}

Dies ermöglicht es Ihnen, dies bei jeder Klasse zu tun, die die IList<> :

var numbers = new List<Tuple<int, string>>
{
    { 1, "one" },
    { 2, "two" },
    { 3, "three" },
    { 4, "four" },
    { 5, "five" },
};
var points = new ObservableCollection<Tuple<double, double, double>>
{
    { 0, 0, 0 },
    { 1, 2, 3 },
    { -4, -2, 42 },
};

Natürlich sind Sie nicht darauf beschränkt, Sammlungen von Tupeln zu erweitern, sondern können Sammlungen eines beliebigen Typs verwenden, für den Sie die spezielle Syntax wünschen.

public static class BigIntegerListExtensions
{
    public static void Add(this IList<BigInteger> list,
        params byte[] value)
    {
        list.Add(new BigInteger(value));
    }

    public static void Add(this IList<BigInteger> list,
        string value)
    {
        list.Add(BigInteger.Parse(value));
    }
}

var bigNumbers = new List<BigInteger>
{
    new BigInteger(1), // constructor BigInteger(int)
    2222222222L,       // implicit operator BigInteger(long)
    3333333333UL,      // implicit operator BigInteger(ulong)
    { 4, 4, 4, 4, 4, 4, 4, 4 },               // extension Add(byte[])
    "55555555555555555555555555555555555555", // extension Add(string)
};

C# 7 wird Unterstützung für in die Sprache eingebaute Tupel hinzufügen, obwohl diese von einem anderen Typ sein werden ( System.ValueTuple stattdessen). Es wäre also gut, Überladungen für Werttupel hinzuzufügen, damit Sie die Möglichkeit haben, diese auch zu verwenden. Leider sind keine impliziten Konvertierungen zwischen den beiden definiert.

public static class ValueTupleListExtensions
{
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
        ValueTuple<T1, T2> item) => list.Add(item.ToTuple());
}

Auf diese Weise wird die Listeninitialisierung noch schöner aussehen.

var points = new List<Tuple<int, int, int>>
{
    (0, 0, 0),
    (1, 2, 3),
    (-1, 12, -73),
};

Aber anstatt sich all diese Mühe zu machen, ist es vielleicht besser, auf die Verwendung von ValueTuple ausschließlich.

var points = new List<(int, int, int)>
{
    (0, 0, 0),
    (1, 2, 3),
    (-1, 12, -73),
};

47voto

Kevin Holditch Punkte 5105

Sie können dies tun, indem Sie den Konstruktor jedes Mal mit einer etwas besseren Methode aufrufen

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

29voto

Asad Saeeduddin Punkte 44986

Eine alte Frage, aber ich mache das normalerweise, um die Dinge etwas lesbarer zu machen:

Func<int, string, Tuple<int, string>> tc = Tuple.Create;

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X