it-swarm.com.de

Was ist C # -analog von C ++ std :: pair?

Ich bin interessiert: Was ist C # 's Analogon von std::pair in C++? Ich fand System.Web.UI.Pair Klasse, aber ich würde etwas vorlagenbasiertes bevorzugen.

Danke!

269

Tuples sind seit .NET4.0 verfügbar und unterstützen Generics:

Tuple<string, int> t = new Tuple<string, int>("Hello", 4);

In früheren Versionen können Sie System.Collections.Generic.KeyValuePair<K, V> oder eine Lösung wie die folgende:

public class Pair<T, U> {
    public Pair() {
    }

    public Pair(T first, U second) {
        this.First = first;
        this.Second = second;
    }

    public T First { get; set; }
    public U Second { get; set; }
};

Und benutze es so:

Pair<String, int> pair = new Pair<String, int>("test", 2);
Console.WriteLine(pair.First);
Console.WriteLine(pair.Second);

Dies gibt aus:

test
2

Oder auch diese verketteten Paare:

Pair<Pair<String, int>, bool> pair = new Pair<Pair<String, int>, bool>();
pair.First = new Pair<String, int>();
pair.First.First = "test";
pair.First.Second = 12;
pair.Second = true;

Console.WriteLine(pair.First.First);
Console.WriteLine(pair.First.Second);
Console.WriteLine(pair.Second);

Das gibt aus:

test
12
true
305
Jorge Ferreira

System.Web.UI enthielt die Klasse Pair, da sie in ASP.NET 1.1 häufig als interne ViewState-Struktur verwendet wurde.

Update August 2017: C # 7.0/.NET Framework 4.7 bietet eine Syntax zum Deklarieren eines Tupels mit benannten Elementen mithilfe von System.ValueTuple struct.

//explicit Item typing
(string Message, int SomeNumber) t = ("Hello", 4);
//or using implicit typing 
var t = (Message:"Hello", SomeNumber:4);

Console.WriteLine("{0} {1}", t.Message, t.SomeNumber);

weitere Syntaxbeispiele finden Sie unter MSDN .

Update Juni 2012: Tuples ist seit Version 4.0 Teil von .NET.

Hier ist ein früherer Artikel, der die Aufnahme in .NET4.0 beschreibt und Unterstützung für Generika:

Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
87
Jay Walker

Leider gibt es keine. Du kannst den ... benutzen System.Collections.Generic.KeyValuePair<K, V> in vielen Situationen.

Alternativ können Sie anonyme Typen verwenden, um Tupel zumindest lokal zu verarbeiten:

var x = new { First = "x", Second = 42 };

Die letzte Alternative besteht darin, eine eigene Klasse zu erstellen.

38
Konrad Rudolph

C # hat Tupel ab Version 4.0.

20
Kenan E. K.

Einige Antworten scheinen einfach falsch zu sein,

  1. sie können kein Wörterbuch verwenden, um die Paare (a, b) und (a, c) zu speichern. Das Paarkonzept sollte nicht mit dem assoziativen Nachschlagen von Schlüsseln und Werten verwechselt werden
  2. viele der oben genannten Codes scheinen verdächtig

Hier ist meine Paarklasse

public class Pair<X, Y>
{
    private X _x;
    private Y _y;

    public Pair(X first, Y second)
    {
        _x = first;
        _y = second;
    }

    public X first { get { return _x; } }

    public Y second { get { return _y; } }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;
        if (obj == this)
            return true;
        Pair<X, Y> other = obj as Pair<X, Y>;
        if (other == null)
            return false;

        return
            (((first == null) && (other.first == null))
                || ((first != null) && first.Equals(other.first)))
              &&
            (((second == null) && (other.second == null))
                || ((second != null) && second.Equals(other.second)));
    }

    public override int GetHashCode()
    {
        int hashcode = 0;
        if (first != null)
            hashcode += first.GetHashCode();
        if (second != null)
            hashcode += second.GetHashCode();

        return hashcode;
    }
}

Hier ist ein Testcode:

[TestClass]
public class PairTest
{
    [TestMethod]
    public void pairTest()
    {
        string s = "abc";
        Pair<int, string> foo = new Pair<int, string>(10, s);
        Pair<int, string> bar = new Pair<int, string>(10, s);
        Pair<int, string> qux = new Pair<int, string>(20, s);
        Pair<int, int> aaa = new Pair<int, int>(10, 20);

        Assert.IsTrue(10 == foo.first);
        Assert.AreEqual(s, foo.second);
        Assert.AreEqual(foo, bar);
        Assert.IsTrue(foo.GetHashCode() == bar.GetHashCode());
        Assert.IsFalse(foo.Equals(qux));
        Assert.IsFalse(foo.Equals(null));
        Assert.IsFalse(foo.Equals(aaa));

        Pair<string, string> s1 = new Pair<string, string>("a", "b");
        Pair<string, string> s2 = new Pair<string, string>(null, "b");
        Pair<string, string> s3 = new Pair<string, string>("a", null);
        Pair<string, string> s4 = new Pair<string, string>(null, null);
        Assert.IsFalse(s1.Equals(s2));
        Assert.IsFalse(s1.Equals(s3));
        Assert.IsFalse(s1.Equals(s4));
        Assert.IsFalse(s2.Equals(s1));
        Assert.IsFalse(s3.Equals(s1));
        Assert.IsFalse(s2.Equals(s3));
        Assert.IsFalse(s4.Equals(s1));
        Assert.IsFalse(s1.Equals(s4));
    }
}
11
Antony

Wenn es um Wörterbücher und dergleichen geht, suchen Sie nach System.Collections.Generic.KeyValuePair <TKey, TValue>.

7
OregonGhost

Ich habe eine C # -Implementierung von Tuples erstellt, die das Problem generisch für zwei bis fünf Werte löst - hier der Blog-Beitrag , die einen Link zur Quelle enthält.

3
Erik Forbes

Je nachdem, was Sie erreichen möchten, sollten Sie KeyValuePair ausprobieren.

Die Tatsache, dass Sie den Schlüssel eines Eintrags nicht ändern können, kann natürlich behoben werden, indem einfach der gesamte Eintrag durch eine neue Instanz von KeyValuePair ersetzt wird.

3
Grimtron

Ich habe die gleiche Frage gestellt, nachdem ich kurz bei Google festgestellt habe, dass es in .NET eine Pair-Klasse gibt, außer in der System.Web.UI ^ ~ ^ ( http://msdn.Microsoft.com/en-us/library/system.web.ui.pair.aspx ) goodness weiß, warum sie es dort anstelle des Kollektionsframeworks ablegen

2
Lyra

Normalerweise erweitere ich die Klasse Tuple in meinen eigenen generischen Wrapper wie folgt:

public class Statistic<T> : Tuple<string, T>
{
    public Statistic(string name, T value) : base(name, value) { }
    public string Name { get { return this.Item1; } }
    public T Value { get { return this.Item2; } }
}

und benutze es so:

public class StatSummary{
      public Statistic<double> NetProfit { get; set; }
      public Statistic<int> NumberOfTrades { get; set; }

      public StatSummary(double totalNetProfit, int numberOfTrades)
      {
          this.TotalNetProfit = new Statistic<double>("Total Net Profit", totalNetProfit);
          this.NumberOfTrades = new Statistic<int>("Number of Trades", numberOfTrades);
      }
}

StatSummary summary = new StatSummary(750.50, 30);
Console.WriteLine("Name: " + summary.NetProfit.Name + "    Value: " + summary.NetProfit.Value);
Console.WriteLine("Name: " + summary.NumberOfTrades.Value + "    Value: " + summary.NumberOfTrades.Value);
2
parliament

Seit .NET 4.0 haben Sie System.Tuple<T1, T2> Klasse:

// pair is implicitly typed local variable (method scope)
var pair = System.Tuple.Create("Current century", 21);
2
Serge Mikhailov

Die PowerCollections-Bibliothek (früher von Wintellect erhältlich, jetzt jedoch auf Codeplex @ http://powercollections.codeplex.com gehostet) hat eine generische Pair-Struktur.

1
James Webster

Abgesehen von benutzerdefinierten Klassen oder .Net 4.0-Tupeln gibt es seit C # 7.0 eine neue Funktion namens ValueTuple, eine Struktur, die in diesem Fall verwendet werden kann. Anstatt zu schreiben:

Tuple<string, int> t = new Tuple<string, int>("Hello", 4);

und Zugriff auf Werte durch t.Item1 und t.Item2, du kannst es einfach so machen:

(string message, int count) = ("Hello", 4);

oder auch:

(var message, var count) = ("Hello", 4);
1
Pawel Gradecki

Um das Obige zum Laufen zu bringen (ich brauchte ein Paar als Schlüssel für ein Wörterbuch). Ich musste hinzufügen:

    public override Boolean Equals(Object o)
    {
        Pair<T, U> that = o as Pair<T, U>;
        if (that == null)
            return false;
        else
            return this.First.Equals(that.First) && this.Second.Equals(that.Second);
    }

und als ich das getan habe, habe ich auch hinzugefügt

    public override Int32 GetHashCode()
    {
        return First.GetHashCode() ^ Second.GetHashCode();
    }

um eine Compiler-Warnung zu unterdrücken.

1
Andrew Stein