在C#中使用一对(三重等)值作为一个值的最佳方法是什么?

也就是说,我想要一个价值元组。

我心中的用例:

Dictionary<Pair, object> 

要么

 Dictionary<Triple, object> 

是否有像Pair或Triple这样的内置类型? 或者实施它的最佳方式是什么?

更新答案中描述了一些通用元组实现,但对于在字典中用作键的元组,您应该另外validation哈希码的正确计算。 在另一个问题中有关于此的更多信息。

更新2我想也值得提醒一下,当你在字典中使用某个值作为键时,它应该是不可变的。

我在C#中实现了一个元组库。 访问http://www.adventuresinsoftware.com/generics/并单击“元组”链接。

内置类

在某些特定情况下,.net框架已经提供了类似元组的类,您可以利用它们。

对和三人组

通用的System.Collections.Generic.KeyValuePair类可以用作adhoc对实现。 这是genericsDictionary在内部使用的类。

或者,您可以使用System.Collections.DictionaryEntry结构,该结构充当基本对,并具有在mscorlib中可用的优势。 然而,不利的是,这种结构不是强类型的。

还可以以System.Web.UI.PairSystem.Web.UI.Triplet类的forms提供Pairs和Triple。 尽管这些类存在于System.Web程序集中,但它们可能非常适合winforms开发。 但是,这些类也不是强类型的,也可能不适用于某些场景,例如通用框架或库。

更高阶的元组

对于更高阶的元组,如果没有滚动自己的类,可能没有一个简单的解决方案。

如果已安装F#语言 ,则可以引用包含一组通用不可变Microsoft.Fsharp.Core.Tuple类的FSharp.Core.dll ,直到通用的六进制文件。 但是,即使可以重新分发未修改的FSharp.Code.dll ,F#也是一种研究语言并且正在进行中,因此这种解决方案可能只对学术界有用。

如果你不想创建自己的类并且引用F#库感到不舒服,那么一个很好的技巧可能在于扩展genericsKeyValuePair类,以便Value成员本身就是嵌套的KeyValuePair。

例如,以下代码说明了如何利用KeyValuePair创建Triples:

 int id = 33; string description = "This is a custom solution"; DateTime created = DateTime.Now; KeyValuePair> triple = new KeyValuePair>(); triple.Key = id; triple.Value.Key = description; triple.Value.Value = created; 

这允许根据需要将类扩展到任意级别。

 KeyValuePair, string>, string> quadruple = new KeyValuePair, string>, string>(); KeyValuePair, string>, string>, string> quintuple = new KeyValuePair, string>, string>, string>(); 

滚动你自己

在其他情况下,您可能需要求助于滚动自己的元组类,这并不难。

您可以创建简单的结构,如下所示:

 struct Pair { private T first_; private R second_; public T First { get { return first_; } set { first_ = value; } } public R Second { get { return second_; } set { second_ = value; } } } 

框架和图书馆

以前已经解决了这个问题,并且确实存在通用框架。 以下是一个这样的框架的链接:

  • 迈克尔·佩里的 元组图书馆 。
 public struct Pair { public T1 First; public T2 Second; } public struct Triple { public T1 First; public T2 Second; public T3 Third; } 

快进到2010年,.NET 4.0现在支持任意n的n元组 。 这些元组按预期实现结构上的平等和比较。

Pair和Triplet是.net中现有的类,请参阅msdn:

三联

我最近遇到了他们,同时玩了viewstate解码

我通常只创建自己的结构,包含值。 它通常更具可读性;)

如果您不想创建自己的类, KeyValuePair是最好的扩展类。

 int id = 33; string description = "This is a custom solution"; DateTime created = DateTime.Now; KeyValuePair> triple = new KeyValuePair>(); triple.Key = id; triple.Value.Key = description; triple.Value.Value = created; 

您可以将其扩展到任意数量的级别。

 KeyValuePair, string, string> quadruple = new KeyValuePair, string, string>(); 

注意 :Triplet和Pair类存在于System.Web -dll中,因此它不适用于除ASP.NET之外的其他解决方案。

您可以相对轻松地创建自己的元组类,唯一可能变得混乱的是您的相等和哈希码覆盖(如果您要在字典中使用它们,则必不可少)。

应该注意的是.Net自己的KeyValuePair struct具有相对较慢的相等和哈希码方法 。

假设这不是你的问题,那么仍然存在代码最终难以弄清楚的问题:

 public Tuple GetSomething() { //do stuff to get your multi-value return } //then call it: var retVal = GetSomething(); //problem is what does this mean? retVal.Item1 / retVal.Item3; //what are item 1 and 3? 

在大多数情况下,我发现创建特定记录类更容易(至少在C#4使这个编译器变得神奇之前)

 class CustomRetVal { int CurrentIndex { get; set; } string Message { get; set; } int CurrentTotal { get; set; } } var retVal = GetSomething(); //get % progress retVal.CurrentIndex / retVal.CurrentTotal; 

还没有提到一个简单的解决方案。 您也可以使用List 。 它内置,高效且易于使用。 当然,它起初看起来有点奇怪,但它完美地完成了它的工作,特别是对于更多的元素数量。

NGenerics–流行的.Net算法和数据结构库,最近向该集合引入了不可变数据结构。

实现的第一个不可变的是pairtuple类。 代码完全覆盖了测试,非常优雅。 你可以在这里查看 。 他们目前正致力于其他不可改变的替代方案,他们应该很快做好准备。

没有内置的ins,但是Pair 类很容易创建。

是的,有System.Web.UI.Pair和System.Web.UI.Triplet(它有一个重载创建者的对类型行为!)

对于第一种情况,我通常使用

 Dictionary, object> 

没有内置类。 您可以使用KeyValuePair或推出自己的实现。

您可以使用System.Collections.Generic.KeyValuePair作为Pair实现。

或者你可以实现自己的,他们并不难:

 public class Triple { public T First {get;set;} public U Second {get;set;} public V Third {get;set;} } 

当然,有一天你可能会遇到Triple(string,int,int)与Triple(int,int,string)不兼容的问题。 也许改为使用System.Xml.Linq.XElement。

F#中还有Tuple <>类型; 你只需要参考FSharp.Core.dll。