Frage

Ich finde mich gelegentlich in C# 3.0 auf der Suche nach Möglichkeiten, um simulieren die Vorstellung von einem Tupel.Im Laufe der Zeit habe ich verschiedene "Arme Mann" - Implementierungen, hier sind ein paar von Ihnen:

Basic-Objekt-Array:

object[] poorTuple = new object[]{foo,bar,baz}; // basic object array

Noch Stärker Typisiert, HoHoHo...

KeyValuePair<TypeA, KeyValuePair<TypeB, TypeC>> poorTuple;

Die Implementierung einer Klasse das Typ-Inferenz (gehoben aus Funktionale Programmierung in der Realen Welt)

public static class Tuple{
  public static Tuple<T1, T2> Create<T1 foo, T2 bar>{
    return new Tuple<T1, T2>(foo, bar);
  }
}
// later: 
var data = Tuple.Create("foo", 42);

Fragen:

  1. Andere Möglichkeiten haben, ein armer Mann ist Tupel in C# 3.0 (oder Sprache der Wahl fehlt die Daten-Struktur).

  2. Was ist das beste Weg, um ein Tupel in C# 3.0 - wenn jemand eine Bibliothek Empfehlung ist willkommen.

  3. An welchem Punkt (ja, verallgemeinern für mich) macht es Sinn einen bestimmten Typ eher als so etwas wie eine Liste oder Tupel?(für die Suche nach Regeln der Daumen)

War es hilfreich?

Lösung

Sie können, erstellen Sie anonyme Typen, die eine ähnliche Funktion wie Tupel, außer mit nützlichen Namen:

var itemsWithChildCounts 
    = myObjects.Select(x => new { Name = x.Name, Count = x.Children.Count() });

Andere Tipps

Hier ist der code für einen generischen Tupel genommen von Bill Wagner Artikel in der April-Ausgabe 2007 Visual Studio Magazine.

public struct Tuple<T1, T2> : IEquatable<Tuple<T1, T2>>
{
    private readonly T1 first;
    public T1 First
    {
        get { return first; }
    }

    private readonly T2 second;
    public T2 Second
    {
        get { return second; }
    } 

    public Tuple(T1 f, T2 s)
    {
        first = f;
        second = s;
    }

    #region IEquatable<Tuple<T1,T2>> Members
    public bool Equals(Tuple<T1, T2> other)
    {
        return first.Equals(other.first) && 
            second.Equals(other.second);
    }

    public override bool Equals(object obj)
    {
        if (obj is Tuple<T1, T2>)
            return this.Equals((Tuple<T1, T2>)obj);
        else
            return false;
    }

    public override int GetHashCode()
    {
        return first.GetHashCode() ˆ second.GetHashCode();
    }
    #endregion
}

Für 1 - 2:Ich bevorzuge die Umsetzung Ihrer eigenen tuple-Klasse.Die Implementierung, die Sie gestohlen haben, ist eine anständige.Es sollte gut funktionieren.

Für 3:Hier ist meine Faustregel, sobald Sie gehen zu Wiederverwendung diese Funktionalität in mehreren Methoden (mit den selben Typen haben die gleiche Bedeutung), oder wenn Sie es verwenden, in einer öffentlichen API, ich denke, es ist Zeit für die Implementierung eines "echten" Klasse mit Ihren speziellen Typen.

  1. Die "Implementierung einer Klasse" - Methode ist so gut wie es geht zu bekommen (und es sollte in der nächsten version von .Eh NET)
  2. Keine Ahnung, ich halten Sie in meine eigene persönliche Bibliothek von Klassen, die für jetzt.
  3. Ich würde erwägen, eine richtige Klasse für Sie als bald wie Sie erhalten für die öffentlichkeit ausgesetzt (d.h.wenn Sie nicht mehr verwendet, nur um zu speichern Sie die zugehörigen Werte für a-Klasse intern).

Da Sie nach Ihrer Meinung gefragt, ich hätte immer eine Art-ich kann nicht herausfinden, ein Grund, nicht zu.

Mehr als oft nicht, können Sie feststellen, dass Sie tatsächlich erforderlich, die Art (der Haupt-entweder zum speichern von zwei Elementen in einer Sammlung oder Rückkehr, die zwei Elemente aus einer Methode call-in beiden Fällen, wenn die Einzelteile sind nicht eng verwandt sind, sind Sie wahrscheinlich etwas falsch machen).

Ich denke, es ist gut, zu schaffen eine neue Art, wenn es Sinn macht die Einführung einer neuen Wert-Satz in Ihrem Programm.Zum Beispiel, wenn Sie schreiben ein komplexer Taschenrechner, dann eine komplexe Zahl geben.Wenn Sie wirklich nur wollen, zu "kleben" ein paar Variablen zusammen, für einen moment, dann ein Tupel ist wahrscheinlich die bessere Wahl.Lassen Sie uns sagen, Sie habe eine einfache Funktion, sammelt zwei zahlen von der Konsole...Sie könnten etwas tun wie:

static void GetNumbers(out int x, out int y) { ... }
...
int x, y;
GetNumbers(out x, out y);

Ich denke, dass es in der Regel sinnvoll, wenn eine "getter" - Funktion hat einen Rückgabewert, aber in diesem Fall kommt es nicht, weil ich nicht wirklich haben zwei Werte zurückgeben.Ich könnte gehen und eine neue Art nennt zwei zahlen und verwenden, aber ich denke, das wird schnell mehr ein problem als eine Lösung.Wenn C# hatte Tupel ich kann in der Lage sein, etwas zu tun, wie die folgenden:

static (int, int) GetNumbers() { ... }
...
int x, y;
(x, y) = GetNumbers();

Nun ist die wirklich interessante Frage ist:obwohl C# nicht über diese Funktion bin ich in der Lage, es zu implementieren, mich mit einer Bibliothek?Der code, den Sie vorschlagen, ist ein Anfang, aber wird nicht zulassen, mich zu ordnen, wie ich getan habe, um im zweiten Beispiel.Ich bin nicht sicher, über C#, aber Sie können sich wirklich verdammt in der Nähe dieses in C++ unter Verwendung der Tatsache, dass ein Funktionsaufruf kann das linke operand des zuweisungsoperators, wenn es Rückgabewert ist eine Referenz geben.Betrachten Sie das folgende:

// this class is implemented much like yours only with C++
template<typename T1, typename T2> class tuple { ... }
...
template<typename T1, typename T2> tuple<T1, T2>& tie(T1 a, T2 b) { ... }
...
template<typename T1, typename T2> tuple<T1, T2> get_numbers() { ... }
...
int x, y;
tie(x, y) = get_numbers();

Ich würde sagen, das ist verdammt nahe...statt (x, y) = wir haben tie(x, y) =.Wenn Sie daran interessiert sind Implementierungsdetails, werde ich verweisen Sie auf die TR1-Bibliothek, wo ich zum ersten mal gelernt, diese:

http://www.boost.org/doc/libs/1_41_0/libs/tuple/doc/tuple_users_guide.html#tiers

So bringen alle diese zurück zu C# 3.0...wir können sicherlich erstellen Sie eine Allgemeine Tupel-Klasse, wie Sie gezeigt haben, aber können wir eine Funktion erstellen, wie die Krawatte zum "entpacken" der Tupel in C#?Ich habe es nicht probiert, klingt nach Spaß.Ohne so etwas wie, dass, ich würde nur ungern lassen Sie ein C# - Tupel Bibliothek vermehren durch meinen code.

Ich dont wie Typ-Inferenz in C#, da es missbraucht zu viel kürzer schreiben.Natürlich ist es eine sehr Coole Funktion, aber die Menschen missbrauchen es IMHO wie in diesem Fall.

In diesem Fall würde ich geben Sie den Typ explizit zu vermeiden, Verwirrungen über den Typ (d.h.vielleicht 42, ist ein langer oder ein byte oder kurz).

Warum also nicht mit einem einfachen Tupel-Klasse, die implementiert werden kann in nur ein paar Zeilen.Und wenn Sie faul sind, können Sie sogar das schreiben einige erweiterungsmethoden für Ihre tuple-Klasse.Das macht das Leben einfacher, sondern auch sauberer.

Sehe nicht den Punkt, der mit einem "fancy" tuple-Klasse anstelle der generischen man Sie präsentiert (außer für die Typ-Inferenz).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top