Любые советы, чтобы упростить работу с Tuples в С#?

Часто вы хотите отправить несколько значений, но из-за низкого уровня использования (т.е. он используется только в одном или двух местах), трудно обосновать создание нового типа.

Тип Tuple<...> и KeyValuePair<,> очень полезен, но для них нет реальной поддержки языка.

Хорошо, хороший трюк для использования в списках кортежей - это создать тип, который расширяет список и добавляет пользовательский метод добавления: например.

public class TupleList<T1,T2> : List<Tuple<T1,T2>>{
    public void Add(T1 key, T2 value){
        base.Add(Tuple.Create(key, value));
    }
}

Это означает, что если у меня есть метод, который принимает IEnumerable<Tuple<int,string>>, я могу использовать следующий код для быстрого создания списка, например:

Foo(new TupleList<int,string>{{1,"one"},{2,"two"},{3,"three"}});

Это упрощает ввод значений в список кортежей, так как нам не нужно постоянно говорить Tuple.Create, и мы получаем почти хороший синтаксис функциональных языков.

Но при работе с кортежем полезно развернуть его на разные компоненты. Этот метод расширения может быть полезен в этом отношении:

    public static void Unwind<T1,T2>(this Tuple<T1,T2> tuple,out T1 var1,out T2 var2)
    {
        var1 = tuple.Item1;
        var2 = tuple.Item2;
    }

Но даже это раздражает, поскольку параметры не являются вообще вариантами. То есть, если T1 является строкой, я не могу отправить объектную переменную, даже если они назначаются, когда я могу сделать разматывание вручную иначе. Я не могу предложить причину, по которой вам может понадобиться эта дисперсия, но если она там, я не понимаю, почему вы хотели бы ее потерять.

У кого-нибудь есть другие советы по созданию рабочих кортежей или упрощению кортежей в С#?

Важным потенциальным использованием кортежей может быть общая memoization. Это очень легко в таких языках, как F #, но сложно в С#.

В настоящее время я использую Tuples для предоставления базы данных MethodBase и массива токенов (констант, объектов или токенов аргументов), поставляемых динамически построенному объекту для построения определенных полей-членов.

Так как я хотел упростить синтаксис для пользователей API, я создал методы Add, которые могут принимать ConstructorInfo или MethodInfo и массив params объектов.

Изменить: Эрик Липпер как обычно имеет отличную мотивацию для использования Tuples здесь, и он даже говорит, что я подозревал, что на самом деле нет поддержки: Какое требование было для кортежа, предназначенного для решения?

Ответ 1

В С# вы можете использовать псевдонимы с закрытыми родовыми типами, которые Tuple, это позволяет вам лучше понять, что предназначено. Не сильно меняет код, но если вы посмотрите на приведенный ниже пример, то лучше то, что возвращает GetTemp.

Без псевдонима:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var result = GetTemp(10, 10);
            Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
        }

        // You give a lat & a long and you get the closest city & temp for it
        static Tuple<double, string> GetTemp(double lat, double @long)
        {
            // just for example
            return Tuple.Create(10d, "Mordor");
        }        
    }
}

С псевдонимом:

namespace ConsoleApplication1
{
    using CityTemp = Tuple<double, string>;

    class Program
    {
        static void Main(string[] args)
        {
            var result = GetTemp(10, 10);
            Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
        }

        // You give a lat & a long and you get the closest city & temp for it
        static CityTemp GetTemp(double lat, double @long)
        {
            // just for example            
            return new CityTemp(10, "Mordor");
        }
    }
}

Ответ 2

Используйте Mono! У них есть экспериментальная поддержка привязки переменных к элементам tuple, чтобы вы могли вызвать метод типа

Tuple<string, string, string, int, string> ParseUri (string url);

используя код типа

(user, password, host, port, path) = ParseUri (url);

Ответ 3

Появится удивительная функция кортежа с С# 7/visual studio 15.

в принципе вы можете сделать что-то вроде этого

static (int x, int y) DoSomething()
{
    return (1, 2);
}

static void Test()
{
    var cool = DoSomething();
    var value = cool.x;
}

Прочитайте в соответствии с post