Что такое С# аналог С++ std:: pair?

Мне интересно, что такое С# аналог С++ std:: pair? Я нашел класс System.Web.UI.Pair, но хотел что-то на основе шаблона.

Спасибо!

Ответ 1

Кортежи доступны с .NET4.0 и поддерживают дженерики:

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

В предыдущих версиях вы можете использовать System.Collections.Generic.KeyValuePair<K, V> или решение, подобное следующему:

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

И используйте его следующим образом:

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

Выводится:

test
2

Или даже эти цепные пары:

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

Это выводит:

test
12
true

Ответ 2

System.Web.UI содержал класс Pair, потому что он широко использовался в ASP.NET 1.1 как внутренняя структура ViewState.

Обновление Aug 2017: С# 7.0/.NET Framework 4.7 предоставляет синтаксис объявления Tuple с именованными элементами с помощью 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);

см. MSDN для получения более синтаксических примеров.

Обновление Jun 2012: Tuples были частью .NET с версии 4.0.

Вот более ранняя статья, описывающая включение в .NET4.0, и поддержка дженериков:

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

Ответ 3

К сожалению, их нет. Во многих ситуациях вы можете использовать System.Collections.Generic.KeyValuePair<K, V>.

В качестве альтернативы вы можете использовать анонимные типы для обработки кортежей, по крайней мере локально:

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

Последняя альтернатива - создать собственный класс.

Ответ 5

Некоторые ответы кажутся просто неправильными,

  • Вы не можете использовать словарь, как хранить пары (a, b) и (a, c). Концепцию пар не следует путать с ассоциативным поиском ключа и значений.
  • много вышеуказанного кода кажется подозрительным

Вот мой класс пар

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

Вот несколько тестовых кодов:

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

Ответ 6

Если речь идет о словарях и т.п., вы ищете System.Collections.Generic.KeyValuePair < TKey, TValue > .

Ответ 7

В зависимости от того, что вы хотите выполнить, вы можете попробовать KeyValuePair.

Тот факт, что вы не можете изменить ключ записи, может быть исправлен, просто заменив всю запись новым экземпляром KeyValuePair.

Ответ 8

Я создал С# реализацию Tuples, которая решает проблему в общем случае между двумя и пятью значениями - здесь сообщение в блоге, которое содержит ссылка на источник.

Ответ 9

Я задавал один и тот же вопрос сразу после быстрого google, я обнаружил, что в .NET есть класс пары, за исключением его в System.Web.UI ^ ~ ^ ( http://msdn.microsoft.com/en-us/library/system.web.ui.pair.aspx) добродетель знает, почему они помещают его вместо рамки коллекций

Ответ 10

С .NET 4.0 у вас есть System.Tuple<T1, T2> класс:

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

Ответ 11

Я обычно расширяю класс Tuple в свою собственную общую оболочку следующим образом:

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

и используйте его так:

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

Ответ 12

Чтобы заставить работу работать (мне нужна была пара в качестве словаря). Мне пришлось добавить:

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

и как только я сделал это, я добавил

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

чтобы подавить предупреждение компилятора.

Ответ 13

Библиотека PowerCollections (ранее доступная от Wintellect, но теперь размещенная на Codeplex @http://powercollections.codeplex.com), имеет общую структуру Pair.

Ответ 14

Помимо настраиваемых классов или .NET-пакетов, поскольку С# 7.0 существует новая функция ValueTuple, которая является структурой, которая может быть использована в этом случае. Вместо написания:

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

и значения доступа через t.Item1 и t.Item2, вы можете просто сделать это следующим образом:

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

или даже:

(var message, var count) = ("Hello", 4);