What is C# analog of C++ std::pair?

↘锁芯ラ 提交于 2019-11-27 02:37:10
Jorge Ferreira

Tuples are available since .NET4.0 and support generics:

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

In previous versions you can use System.Collections.Generic.KeyValuePair<K, V> or a solution like the following:

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; }
};

And use it like this:

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

This outputs:

test
2

Or even this chained pairs:

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

That outputs:

test
12
true

System.Web.UI contained the Pair class because it was used heavily in ASP.NET 1.1 as an internal ViewState structure.

Update Aug 2017: C# 7.0 / .NET Framework 4.7 provides a syntax to declare a Tuple with named items using the 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);

see MSDN for more syntax examples.

Update Jun 2012: Tuples have been a part of .NET since version 4.0.

Here is an earlier article describing inclusion in.NET4.0 and support for generics:

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

Unfortunately, there is none. You can use the System.Collections.Generic.KeyValuePair<K, V> in many situations.

Alternatively, you can use anonymous types to handle tuples, at least locally:

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

The last alternative is to create an own class.

C# has tuples as of version 4.0.

Antony

Some answers seem just wrong,

  1. you can't use dictionary how would store the pairs (a,b) and (a,c). Pairs concept should not be confused with associative look up of key and values
  2. lot of the above code seems suspect

Here is my pair class

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;
    }
}

Here is some test code:

[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));
    }
}

If it's about dictionaries and the like, you're looking for System.Collections.Generic.KeyValuePair<TKey, TValue>.

Depending on what you want to accomplish, you might want to try out KeyValuePair.

The fact that you cannot change the key of an entry can of course be rectified by simply replacing the entire entry by a new instance of KeyValuePair.

I created a C# implementation of Tuples, which solves the problem generically for between two and five values - here's the blog post, which contains a link to the source.

I was asking the same question just now after a quick google I found that There is a pair class in .NET except its in the System.Web.UI ^ ~ ^ (http://msdn.microsoft.com/en-us/library/system.web.ui.pair.aspx) goodness knows why they put it there instead of the collections framework

Since .NET 4.0 you have System.Tuple<T1, T2> class:

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

I typically extend the Tuple class into my own generic wrapper as follows:

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; } }
}

and use it like 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);

On order to get the above to work (I needed a pair as the key of a dictionary). I had to add:

    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);
    }

and once I did that I also added

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

to suppress a compiler warning.

The PowerCollections library (formerly available from Wintellect but now hosted on Codeplex @ http://powercollections.codeplex.com) has a generic Pair structure.

Pawel Gradecki

Apart from custom class or .Net 4.0 Tuples, since C# 7.0 there is a new feature called ValueTuple, which is a struct that can be used in this case. Instead of writing:

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

and access values through t.Item1 and t.Item2, you can simply do it like that:

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

or even:

(var message, var count) = ("Hello", 4);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!