代码之家  ›  专栏  ›  技术社区  ›  Massimiliano

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

  •  20
  • Massimiliano  · 技术社区  · 16 年前

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

    我脑海中的用例:

    Dictionary<Pair<string, int>, object>
    

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

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

    更新 答案中描述了一些通用的元组实现,但对于用作字典键的元组,您应该额外验证哈希码的正确计算。在另一篇文章中提供更多信息 question .

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

    16 回复  |  直到 8 年前
        1
  •  6
  •   Michael L Perry    16 年前

    内置类

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

    成对和三重

    通用的 System.Collections.Generic.KeyValuePair 类可以用作即席对实现。这是一个班级 通用字典内部使用。

    或者,你也可以凑合着用 System.Collections.DictionaryEntry 作为基本配对的结构,具有以下优点 在mscorlib中可用。然而,不利的一面是,这种结构不是 强烈类型。

    双人和三人组也有以下形式 System.Web.UI.Pair System.Web.UI.Triplet 班级。尽管这些班级生活在 系统。网络 会议 它们可能非常适合winforms开发。然而,这些课程是 也不是强类型,在某些情况下可能不适合,例如通用框架或库。

    高阶元组

    对于高阶元组,除了滚动自己的类之外,可能还有 这不是一个简单的解决方案。

    如果您已安装 F# language ,你可以参考 FSharp。Core.dll 它包含一组通用的不可变变量 Microsoft.Fsharp.Core.Tuple 班 直到通用的六元组。然而,即使未经修改 FSharp。Code.dll 可以重新分发,F#是一种研究语言,也是一项正在进行的工作,因此 这种解决方案可能只会引起学术界的兴趣。

    如果你不想创建自己的类并且感到不舒服 引用F#库,一个巧妙的技巧可能是扩展通用的KeyValuePair类,使Value成员本身就是一个嵌套的KeyValuePair。

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

    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; }
        }
    }
    

    框架与库

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

        2
  •  20
  •   community wiki 2 revs Maxime Labelle    8 年前
    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;
    }
    
        3
  •  12
  •   Timothy Carter    16 年前

    快进到2010年。NET 4.0现在支持 n-tuples of arbitrary n 这些元组实现了预期的结构相等和比较。

        4
  •  11
  •   Mauricio Scheffer    14 年前

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

    Triplet

    Pair

    我最近在玩viewstate解码时遇到了它们

        5
  •  9
  •   Adam Vigh    16 年前

    我在C#中实现了一个元组库。参观 http://www.adventuresinsoftware.com/generics/ 然后点击“元组”链接。

        6
  •  3
  •   Grad van Horck    16 年前

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

        7
  •  2
  •   Seb Nilsson    16 年前

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

    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>();
    

    笔记 :班级 三联 一对 存在于 系统。网络 -dll,因此它不太适合ASP以外的其他解决方案。网。

        8
  •  2
  •   Keith    16 年前

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

    应该指出的是。Net自己的 KeyValuePair<TKey,TValue> 结构体具有 relatively slow equality and hashcode methods .

    假设这对你来说不是问题,那么代码最终仍然很难弄清楚:

    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;
    
        9
  •  2
  •   mafu    15 年前

    一个简单的解决方案尚未被提及。你也可以只使用 List<T> 它是内置的,高效且易于使用。诚然,起初它看起来有点奇怪,但它做得很好,尤其是对于大量的元素。

        10
  •  1
  •   husayt    15 年前

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

    第一个实现不可变的是 一对 元组 班级。该代码经过了很好的测试,非常优雅。你可以查一下 here 。他们目前正在研究其他不可改变的替代方案,预计很快就会准备就绪。

        11
  •  0
  •   Will    16 年前

    没有内置,但有一对<T、 R>创建类很简单。

        12
  •  0
  •   ballpointpeon    16 年前

    是的,有系统。网状物。UI。配对和系统。网状物。UI。Triplet(它有一个过载的Pair类型行为创建者!)

        13
  •  0
  •   Jonas Lincoln    16 年前

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

    Dictionary<KeyValuePair<string, int>, object>
    
        14
  •  0
  •   aku    16 年前

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

        15
  •  0
  •   Amy B    16 年前

    你可以使用系统。收藏。通用。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)不兼容的问题。也许用系统。Xml。林克。取而代之的是XElement。

        16
  •  0
  •   TraumaPony    16 年前

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