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

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

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

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

    我脑海中的用例:

    Dictionary<Pair<string, int>, object>
    

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

    是否有像“双”或“三”这样的内置类型?或者什么是实现它的最佳方式?

    更新 答案中描述了一些通用的元组实现,但是对于在字典中用作键的元组,您应该另外验证哈希代码的正确计算。在另一本书里有更多关于这个的信息 question .

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

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

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

        2
  •  20
  •   community wiki 2 revs Maxime Labelle    7 年前

    建筑类

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

    成对和三倍

    通用的 System.Collections.Generic.KeyValuePair 类可以用作特殊对实现。这是那个 通用字典在内部使用。

    或者,您可以使用 System.Collections.DictionaryEntry 作为基本对的结构,具有 在mscorlib中可用。然而,从反面来看,这种结构不是 强类型的。

    双和三重的形式也可以 System.Web.UI.Pair System.Web.UI.Triplet 类。即使这些班级生活在 网络系统 装配 它们可能非常适合WinForms开发。但是,这些类是 也不是强类型,可能不适用于某些场景,例如通用框架或库。

    高阶元组

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

    如果安装了 F# language ,您可以参考 FSARP.COR.DLL 包含一组不可变的泛型 Microsoft.Fsharp.Core.Tuple 班 最多通用六元组。然而,即使是一个未经修改的 FSARP.CODE.DLL 可以重新分配,F是一种研究语言,也是一项正在进行的工作,因此 这一解决方案可能只在学术界引起关注。

    如果你不想创建自己的类,并且感到不舒服 引用F库时,一个巧妙的技巧是扩展通用的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>();
    

    翻滚你自己

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

    您可以创建这样的简单结构:

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

    框架与库

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

        3
  •  12
  •   Timothy Carter    16 年前
    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;
    }
    
        4
  •  11
  •   Mauricio Scheffer    14 年前

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

        5
  •  9
  •   Adam Vigh    16 年前

    pair和triplet是.NET中现有的类。请参阅msdn:

    Triplet

    Pair

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

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

    注释 班级 三重态 一对 存在于 网络系统 -动态链接库,因此它不太适用于ASP.NET以外的其他解决方案。

        8
  •  2
  •   Keith    16 年前

    您可以相对容易地创建自己的tuple类,唯一可能导致混乱的是您的相等性和哈希代码重写(如果您要在字典中使用它们,则是必需的)。

    应该注意,.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    14 年前

    一个简单的解决方案尚未被提及。您也可以使用 List<T> . 它是内置的,高效的,易于使用。当然,一开始看起来有点奇怪,但它的工作做得很完美,尤其是对于大量元素。

        10
  •  1
  •   husayt    15 年前

    nGenerics是最流行的.NET算法和数据结构库,最近已经推出 不变的 集合的数据结构。

    第一个不可变的实现是 一对 元组 类。代码被测试覆盖得很好,非常优雅。你可以查一下 here . 他们目前正在研究其他不变的替代方案,应该很快就准备好了。

        11
  •  0
  •   Will    16 年前

    没有内置的,但是创建一对lt;t、r>类是很简单的。

        12
  •  0
  •   ballpointpeon    16 年前

    是的,有system.web.ui.pair和system.web.ui.triplet(它有一个重载的成对类型行为创建者!)

        13
  •  0
  •   Jonas Lincoln    16 年前

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

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

    没有为此而内置的类。你可以使用 KeyValuePair 或者自己展开实现。

        15
  •  0
  •   Amy B    16 年前

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

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

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

    当然,有一天你可能会遇到一个问题,即三重(string,int,int)与三重(int,int,string)不兼容。可能改为使用system.xml.linq.xelement。

        16
  •  0
  •   TraumaPony    16 年前

    在F中还有tuple<>类型,您只需要引用fsharp.core.dll即可。