通常你想发送多个值,但由于使用率低(即它只在一两个地方使用),很难证明创建一个新类型的合理性.
该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像往常一样有很好的动机在这里使用元组,他甚至说我怀疑那里真的没有支持: 元组设计要解决的要求是什么?
在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)
使用单声道!他们对将变量绑定到元组成员提供了实验性支持,因此您可以调用类似的方法
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)