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

Mic*_*l B 10 .net c# tuples

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

Tuple<...>KeyValuePair<,>类型是非常有用的,但不是他们真正的语言支持.

好吧,一种用于元组列表的好方法是创建一个扩展List并添加自定义add方法的类型:例如

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

这意味着如果我有一个方法IEnumerable<Tuple<int,string>>,我可以使用以下代码快速建立列表,如下::

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

这使得将值变为元组列表变得更容易,因为我们不必经常说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;
    }
Run Code Online (Sandbox Code Playgroud)

但即便如此,因为输出参数根本不是变体.也就是说,如果T1是一个字符串,即使它们是可分配的,我也不能发送一个对象变量,否则就像我可以用手展开一样.我无法提出你可能想要这种差异的原因,但如果它存在,我无法理解为什么你会想要失去它.

任何人都有其他技巧来制作工作元组,或者在C#中更容易像元组一样的元组?

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

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

由于我想在API使用者身上简化语法,因此我创建了可以使用a ConstructorInfo或a MethodInfo和params对象数组的Add方法.

编辑:Eric Lippert像往常一样有很好的动机在这里使用元组,他甚至说我怀疑那里真的没有支持: 元组设计要解决的要求是什么?

Rob*_*ean 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");
        }        
    }
}
Run Code Online (Sandbox Code Playgroud)

使用别名:

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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sam*_*ack 4

使用单声道!他们对将变量绑定到元组成员提供了实验性支持,因此您可以调用类似的方法

Tuple<string, string, string, int, string> ParseUri (string url);
Run Code Online (Sandbox Code Playgroud)

使用类似的代码

(user, password, host, port, path) = ParseUri (url);
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常糟糕的建议。当然,这个功能很简洁,但是“使用 Mono”并不是很多人都能做出的决定。 (13认同)
  • 不幸的是,这看起来非常好,对于工作来说,我无法更改我们编译的运行时。 (6认同)