我正在研究元组的新C#特性。我好奇,元组设计要解决什么问题?
你在应用中使用了什么元组?
更新
感谢到目前为止的答案,让我看看我是否在脑子里直截了当。 已经指出了一个元组的一个很好的例子作为坐标。这看起来不错吗?
var coords = Tuple.Create(geoLat,geoLong);
然后像这样使用元组:
var myLatlng = new google.maps.LatLng("+ coords.Item1 + ", "+ coords.Item2 + ");
这是对的吗?
答案 0 :(得分:117)
在编写程序时,想要逻辑地将一组没有足够通用性的值组合在一起来证明创建一个类是极其常见的。
许多编程语言允许您在逻辑上将一组不相关的值组合在一起,而无需仅以一种方式创建类型:
void M(int foo, string bar, double blah)
逻辑上,这与采用一个参数的方法M完全相同,该参数是int,string,double的3元组。但我希望你不会真正做到:
class MArguments
{
public int Foo { get; private set; }
... etc
除非MArguments在业务逻辑中有其他含义。
“在一些比一个类更轻量级的结构中将一堆其他不相关的数据组合在一起”这一概念在很多很多地方都很有用,不仅适用于方法的形式参数列表。当一个方法有两件事要返回时,或者你想要从两个数据而不是一个数据中键入一个字典时,这很有用,依此类推。
像F#这样支持元组类型的语言本身为用户提供了很大的灵活性;它们是一组非常有用的数据类型。 BCL团队决定与F#团队合作,为框架标准化一种元组类型,以便每种语言都能从中受益。
但是,此时没有语言支持C#中的元组。元组只是与任何其他框架类一样的另一种数据类型;他们没什么特别的。我们正在考虑在假设的未来版本的C#中为元组添加更好的支持。如果有人对你希望看到哪些涉及元组的功能有任何想法,我很乐意将它们传递给设计团队。现实场景比理论思考更有说服力。
答案 1 :(得分:22)
元组提供集合的不可变实现
除了元组的常见用法:
不可变对象本质上是线程安全的:
不可变对象在多线程应用程序中很有用。多个线程可以对不可变对象表示的数据起作用,而不用担心其他线程正在更改数据。因此,不可变对象被认为比可变对象更具线程安全性。
来自维基百科上的"Immutable Object"
答案 2 :(得分:12)
如果您的方法需要在响应中返回多个新对象,它会提供ref
或out
的替代方法。
它还允许您使用内置类型作为返回类型,如果您只需要将两个或三个现有类型混搭,并且您不希望仅为了添加类/结构这个组合。 (曾经希望函数可以返回匿名类型吗?这是对这种情况的部分答案。)
答案 3 :(得分:9)
拥有一个“对”类型通常很有用,只是在快速情况下使用(比如从方法中返回两个值)。元组是F#等函数式语言的核心部分,C#在此过程中将它们选中。
答案 4 :(得分:5)
从函数
返回两个值非常有用答案 5 :(得分:4)
就个人而言,当你处于调查周期或者只是“玩”时,我发现元组是发展的一个反复部分。因为Tuple是通用的,所以在处理泛型参数时我倾向于考虑它 - 特别是当想要开发通用代码时,我从代码端开始,而不是问自己“我怎么会喜欢这个调用看?“。
我经常意识到元组形成的集合成为列表的一部分,并且盯着List>并没有真正表达清单的意图,或它是如何工作的。我经常“生活”它,但发现自己想要操纵列表,并改变一个值 - 此时,我不一定要为此创建一个新的元组,因此我需要创建自己的类或结构持有它,所以我可以添加操作代码。
当然,总有扩展方法 - 但通常你不想将额外的代码扩展到通用实现。
有时候我想把数据表示为元组,而不是有元组可用。 (VS2008)在这种情况下我刚刚创建了自己的Tuple类 - 而且我没有让它成为线程安全的(不可变的)。
所以我想我认为Tuples是懒惰的编程,代价是丢失一个描述它的目的的类型名称。另一个代价是你必须声明Tuple的签名,无论它被用作参数。在一些开始变得臃肿的方法之后,你可能会像我一样觉得值得上课,因为它清理了方法签名。
我倾向于首先让这个类成为你已经在工作的类的公共成员。但是当它超越简单的一组值时,就会得到它自己的文件,然后我把它移出包含类。
回想起来,我相信当我不想去写课时,我会使用元组,而只是想想想我现在写的是什么。这意味着元组的签名可能会在半小时内发生很大的变化,同时我会弄清楚这个方法需要哪些数据,以及它如何返回它将返回的值。
如果我有机会重构代码,那么我经常会质疑一个元组的位置。
答案 6 :(得分:2)
自2010年以来的老问题,现在2017年Dotnet变得更加聪明。
C#7为元组引入了语言支持,它使用新的,更有效的元组类型为元组的字段启用语义名称。
在vs 2017和.Net 4.7(或安装nuget包System.ValueTuple)中,您可以以非常有效和简单的方式创建/使用元组:
var person = (Id:"123", Name:"john"); //create tuble with two items
Console.WriteLine($"{person.Id} name:{person.Name}") //access its fields
从方法中返回多个值:
public (double sum, double average) ComputeSumAndAverage(List<double> list)
{
var sum= list.Sum();
var average = sum/list.Count;
return (sum, average);
}
How to use:
var list=new List<double>{1,2,3};
var result = ComputeSumAndAverage(list);
Console.WriteLine($"Sum={result.sum} Average={result.average}");
有关详细信息,请参阅:https://docs.microsoft.com/en-us/dotnet/csharp/tuples
答案 7 :(得分:1)
当您不想创建特定类型时,元组通常用于从函数返回多个值。如果您熟悉Python,Python已经有很长时间了。
答案 8 :(得分:1)
常见的用法可能是避免创建只包含2个字段的类/结构,而是创建一个Tuple(或者现在为KeyValuePair)。 有用作为返回值,避免将N传递给params ......
答案 9 :(得分:1)
从函数返回多个值。如果只返回x或y或z,getCoordinates()不是很有用,但是使一个完整的类和对象保持三个整数也似乎非常重要。
答案 10 :(得分:0)
我发现在C#中刷新KeyValuePair以迭代字典中的键值对。
答案 11 :(得分:0)
我偶然发现了元组和键值对之间的这种性能基准,你可能会发现它很有趣。总而言之,它说Tuple有优势,因为它是一个类,因此它存储在堆中,而不是存储在堆栈中,当作为参数传递时,它的指针是唯一的东西。但KeyValuePair是一个结构体,因此分配速度更快,但使用时速度较慢。
答案 12 :(得分:0)
从函数返回值时非常有用。我们可以返回多个值,这在某些情况下非常安全。