在C#中使用元组更容易的任何提示?

时间:2010-11-24 17:32:22

标签: c# .net tuples

通常你想发送多个值,但由于使用率低(即只在一两个地方使用),很难证明创建一个新类型的合理性。

Tuple<...>KeyValuePair<,>类型非常有用,但对它们没有真正的语言支持。

很好,用于元组列表的一个很好的技巧是创建一个扩展List并添加自定义add方法的类型: e.g。

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#中更轻松地创建工作元组或类似对象:

元组的一个重要潜在用途可能是通用的memoization。这在F#等语言中非常容易,但在C#中却很难。

我目前正在使用Tuples提供一个MethodBase和一个标记数组(常量,对象或参数标记),提供给动态构建的对象以构造某些成员字段。

由于我想在API使用者身上简化语法,因此我创建了可以采用ConstructorInfoMethodInfo以及params对象数组的Add方法。

编辑: Eric Lippert像往常一样在这里使用元组有很好的动机,他甚至说我怀疑那里真的没有支持: What requirement was the tuple designed to solve?

3 个答案:

答案 0 :(得分:5)

在C#中,您可以为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");
        }
    }
}

答案 1 :(得分:4)

使用单声道!他们对binding variables to tuple members有实验支持,因此您可以调用类似

的方法
Tuple<string, string, string, int, string> ParseUri (string url);

使用

之类的代码
(user, password, host, port, path) = ParseUri (url);

答案 2 :(得分:2)

c#7 / visual studio 15将会出现一个非常棒的元组功能。

基本上你可以这样做

npm i <package> --save && npm uninstall <package>

根据https://github.com/sahat/satellizer

阅读
相关问题