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

Меня интересует: что такое аналог std::pair в C ++ в C #? Я нашел System.Web.UI.Pair класс, но предпочел бы что-нибудь на основе шаблонов.

Спасибо!


person Alexander Prokofyev    schedule 03.10.2008    source источник
comment
Некоторое время назад у меня был такой же запрос, но чем больше я думал об этом, вы можете просто развернуть свой собственный класс сопряжения с явными типами и полями классов вместо общих First и Second. Это делает ваш код более читабельным. Класс сопряжения может состоять всего из 4 строк, поэтому вы не сэкономите много, повторно используя общий класс Pair ‹T, U›, и ваш код будет более читабельным.   -  person Mark Lakata    schedule 01.05.2012


Ответы (14)


Кортежи доступны начиная с .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
person Jorge Ferreira    schedule 03.10.2008
comment
См. Мой пост о добавлении метода Equals - person Andrew Stein; 23.10.2009
comment
Tuple ‹› теперь является лучшим решением. - person dkantowitz; 03.08.2012
comment
Поскольку параметры типа, принадлежащие универсальному классу, не могут быть выведены в выражении создания объекта (вызов конструктора), авторы BCL создали неуниверсальный вспомогательный класс под названием Tuple. Поэтому вы можете сказать Tuple.Create("Hello", 4), что немного проще, чем new Tuple<string, int>("Hello", 4). (Кстати, .NET4.0 уже здесь с 2010 года.) - person Jeppe Stig Nielsen; 15.08.2012
comment
Имейте в виду, что Tuple<> реализует твердые Equals и GetHashCode с семантикой значений, и это здорово. Имейте это в виду при реализации собственных кортежей. - person nawfal; 01.01.2014
comment
Это явно не работает из-за Equals и GetHashCode - person julx; 07.07.2017
comment
Не [Struct], а [Class]? Я не думаю, что он работает так же, как [std :: pair] в случае использования [Pair] в качестве ключа словаря C # - person siamenock; 09.12.2019

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

Обновление, август 2017 г .: C # 7.0 / .NET Framework 4.7 предоставляет синтаксис для объявления кортежа с именованными элементами с помощью _ 3_ 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.

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

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

Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
person Jay Walker    schedule 04.08.2009
comment
Обратите внимание, что кортежи доступны только для чтения. То есть этого делать нельзя: tuple.Item1 = 4; - person skybluecodeflier; 21.06.2011
comment
Кортежи - это именно то, что я искал. Спасибо. - person gligoran; 21.08.2011

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

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

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

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

person Konrad Rudolph    schedule 03.10.2008
comment
Для ясности: анонимные типы также доступны только для чтения - msdn . - person bsegraves; 16.03.2012

Начиная с версии 4.0 C # содержит кортежи.

person Kenan E. K.    schedule 04.08.2009

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

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

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

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));
    }
}
person Antony    schedule 14.01.2010
comment
Если вы не реализуете IEquatable, вы получите бокс. Еще предстоит проделать дополнительную работу, чтобы правильно завершить урок. - person Jack; 18.09.2012

Если речь идет о словарях и тому подобном, вы ищете System.Collections.Generic.KeyValuePair ‹TKey, TValue›.

person OregonGhost    schedule 03.10.2008

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

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

person Grimtron    schedule 03.10.2008

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

person Erik Forbes    schedule 29.01.2009

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

person Community    schedule 14.10.2008
comment
Я знаю о System.Web.UI.Pair. Хотел общий класс. - person Alexander Prokofyev; 15.10.2008
comment
System.Web.UI.Pair запечатан. Вы не можете наследовать от него (в случае, если вы хотите добавить типобезопасные средства доступа). - person Martin Vobr; 11.02.2010

Начиная с .NET 4.0 у вас есть System.Tuple<T1, T2> класс:

// pair is implicitly typed local variable (method scope)
var pair = System.Tuple.Create("Current century", 21);
person Serge Mikhailov    schedule 10.03.2011
comment
@Alexander, вы можете легко заглянуть в .NET 3.5 документы на Tuple - person Serge Mikhailov; 16.03.2011
comment
Внизу написано: Информация о версии NET Framework Поддерживается в: 4 - person Alexander Prokofyev; 18.03.2011
comment
@ Александр: Хорошо, верно. (Хотя это заставило меня задуматься, почему они сделали эту страницу специфичной для .NET 3.5) - person Serge Mikhailov; 18.03.2011

Я обычно расширяю класс 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);
person parliament    schedule 03.03.2013

Помимо настраиваемого класса или кортежей .Net 4.0, начиная с C # 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);
person Pawel Gradecki    schedule 26.04.2017

Для того, чтобы все вышеперечисленное работало (мне нужна была пара в качестве ключа словаря). Пришлось добавить:

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

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

person Andrew Stein    schedule 23.10.2009
comment
Вы должны найти лучший алгоритм хэш-кода, чем этот, попробуйте использовать 37 + 23 * (h1 + 23 * (h2 + 23 * (h3 + ...))). Это сделает (A, B) отличным от (B, A ), т.е. изменение порядка повлияет на код. - person Lasse V. Karlsen; 23.10.2009
comment
Комментарий принят .. В моем случае я просто пытался подавить ослабление компилятора, и в любом случае T - это String, а U - Int32 ... - person Andrew Stein; 25.10.2009

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

person James Webster    schedule 19.11.2009