2010-11-24 3 views
10

Часто вы хотите отправить несколько значений, но из-за низкого уровня использования (т. Е. Он используется только в одном или двух местах), трудно создать новый тип.Любые советы, чтобы упростить работу с Tuples в C#?

Тип 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 является строкой, я не могу отправить объектную переменную, даже если они назначаются, когда я могу сделать разматывание вручную иначе. Я действительно не могу предложить причину, по которой вам может понадобиться эта дисперсия, но если она там, я не понимаю, почему вы хотели бы ее потерять.

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

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

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

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

Edit: Эрик Липперт, как обычно, имеет отличную мотивацию для использования кортежей здесь, и он даже говорит, что я подозревал, что на самом деле нет никакой поддержки: What requirement was the tuple designed to solve?

+0

Можете ли вы показать нам свой прецедент, где вы предпочитаете передавать параметры типа `object`, а не переменные, набранные для того, что они должны быть на самом деле? Покажите нам, как вы хотите называть «Unwind» с небольшим контекстом. – 2010-11-24 17:37:17

+1

параметры жесткие, поэтому они не предлагаются в качестве выбора. Я бы убил за поддержку API, как F #, которая превращает параметры в кортежи. – 2010-11-24 18:49:27

ответ

4

Использование Mono! Они имеют экспериментальную поддержку binding variables to tuple members так что вы могли бы назвать метод, как

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

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

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

В C# вы можете псевдоним закрытого общие типов, которые кортеж, это позволяет обеспечить некоторые лучше понимание того, что предназначено. Не сильно меняет код, но если вы посмотрите на приведенный ниже пример, то лучше то, что возвращает 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

Там будет удивительный набор функция приходит с C# 7/Visual Studio 15.

в основном вы можете сделать soething подобный

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

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

Прочитано согласно post