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

我想到的用例:

Dictionary<Pair<string, int>, object>

或者

Dictionary<Triple<string, int, int>, object>

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

更新 答案中描述了一些通用的元组实现,但是对于用作字典中的键的元组,您还应该验证哈希码的正确计算。另一个方面有更多信息 问题.

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

有帮助吗?

解决方案

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

其他提示

内置类

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

对和三人组

通用的System.Collections.Generic.KeyValuePair类可以用作临时对实现。这是通用词典内部使用的类。

或者,您也许可以凑合使用System.Collections.DictionaryEntry充当基本对的结构,具有在Mscorlib中可用的优势。然而,在偏低的一侧是,这种结构不是强烈键入的。

对和三元组也可以以以下形式提供:系统.Web.UI.Pair系统.Web.UI.三元组 类。尽管这些课程住在 系统.Web 组装它们可能非常适合Winforms开发。但是,这些类也不是强烈键入的,在某些情况下可能不适合使用,例如一般有目的的框架或库。

高阶元组

对于高阶元组,缺乏自己的课程,可能没有一个简单的解决方案。

如果您已经安装了F#语言, ,你可以参考 FSharp.Core.dll 包含一组通用的不可变的Microsoft.Fsharp.Core.Tuple 课程到通用分解。然而,即使未经修改 FSharp.Code.dll可以重新分配,F#是一种研究语言,并且正在进行中的工作,因此该解决方案只有在学术界才能引起人们的关注。

如果您不想创建自己的课程,并且不舒服引用f#库,那么一个漂亮的技巧可以包括扩展通用的keyValuepair类,以便值成员本身就是嵌套的keyValuepair。

例如,以下代码说明了如何利用KeyValuepair来创建三元组:

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

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

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

自己动手

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

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

struct Pair<T, R>
{
    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<T1, T2>
{
    public T1 First;
    public T2 Second;
}

public struct Triple<T1, T2, T3>
{
    public T1 First;
    public T2 Second;
    public T3 Third;
}

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

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

三胞胎

一对

我最近在玩视图状态解码时遇到了它们

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

键值对 如果您不想创建自己的类,则这是最好的扩展类。

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

您可以根据需要将其扩展到任意多个级别。

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

笔记: :课程 三胞胎一对 存在于里面 系统.Web-dll,因此它不太适合除 ASP.NET 之外的其他解决方案。

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

需要注意的是.Net自己的 KeyValuePair<TKey,TValue> 结构体有 相对较慢的相等和哈希码方法.

假设这不是您关心的问题,但仍然存在代码最终难以弄清楚的问题:

public Tuple<int, string, int> 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<T>. 。它是内置的,高效且易于使用。诚然,它一开始看起来有点奇怪,但它完美地完成了它的工作,特别是对于大量的元素。

NGenerics - 流行的 .Net 算法和数据结构库,最近推出 不可变的 数据结构到集合。

第一个实施的不可变的是 一对元组 类。该代码经过充分测试,非常优雅。你可以检查一下 这里. 。他们目前正在研究其他不可变的替代方案,应该很快就会准备好。

没有内置函数,但创建 Pair<T,R> 类很简单。

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

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

Dictionary<KeyValuePair<string, int>, object>

没有为此的内置类。您可以使用 键值对 或推出您自己的实施。

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

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

public class Triple<T, U, V>
{
  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。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top