多值字典


76

如何在C#中创建多值字典?

例如Dictionary<T,T,T>,第一个T是键,其他两个是值。

因此这是可能的: Dictionary<int,object,double>

谢谢

Answers:


62

只需创建一个Pair<TFirst, TSecond>类型并将其用作您的值即可。

我在C#中的Depth源代码中有一个示例。为简单起见,此处转载:

using System;
using System.Collections.Generic;

public sealed class Pair<TFirst, TSecond>
    : IEquatable<Pair<TFirst, TSecond>>
{
    private readonly TFirst first;
    private readonly TSecond second;

    public Pair(TFirst first, TSecond second)
    {
        this.first = first;
        this.second = second;
    }

    public TFirst First
    {
        get { return first; }
    }

    public TSecond Second
    {
        get { return second; }
    }

    public bool Equals(Pair<TFirst, TSecond> other)
    {
        if (other == null)
        {
            return false;
        }
        return EqualityComparer<TFirst>.Default.Equals(this.First, other.First) &&
               EqualityComparer<TSecond>.Default.Equals(this.Second, other.Second);
    }

    public override bool Equals(object o)
    {
        return Equals(o as Pair<TFirst, TSecond>);
    }

    public override int GetHashCode()
    {
        return EqualityComparer<TFirst>.Default.GetHashCode(first) * 37 +
               EqualityComparer<TSecond>.Default.GetHashCode(second);
    }
}

2
与普通的KeyValuePair相比有什么优势?使用KeyValuePair时会产生某种开销吗?
tanascius

1
主要是强调上的差异-虽然KeyValuePair确实确实封装了一对值,但这暗示着它们之间存在一种特殊的关系……而事实并非如此。
乔恩·斯基特

18
这与.Net 4.0中的Tuple相同吗?
adam0101 2010年

2
@ adam0101:差不多,是的。
乔恩·斯基特

4
@BasselAlkhateeb:如果您不希望能够重新获得这些值,那是的,这很好...
Jon Skeet 2012年

64

如果您尝试将值分组在一起,那么这可能是创建简单结构或类并将其用作字典中的值的绝佳机会。

public struct MyValue
{
    public object Value1;
    public double Value2;
}

那你就可以拥有字典

var dict = new Dictionary<int, MyValue>();

您甚至可以更进一步,实现自己的字典类,该字典类将处理所需的任何特殊操作。例如,如果您想让Add方法接受一个int,object和double

public class MyDictionary : Dictionary<int, MyValue>
{
    public void Add(int key, object value1, double value2)
    {
        MyValue val;
        val.Value1 = value1;
        val.Value2 = value2;
        this.Add(key, val);
    }
}

那么您只需像这样实例化并添加到字典中,就不必担心创建'MyValue'结构:

var dict = new MyDictionary();
dict.Add(1, new Object(), 2.22);

30
Dictionary<T1, Tuple<T2, T3>>

编辑:对不起-我忘了你直到.NET 4.0出来后才得到元组。天哪!


1
元组位于.NET 4.0 BCL中,并且与C#4.0不相关。C#4.0功能没有提及元组支持。请更正您的答案。
Eriawan Kusumawardhono

元组的问题是未命名值。
ProfK 2014年

2
此外,元组值是只读的,在某些情况下可能是可行的,但在使用它们之前应予以考虑。
塞巴斯蒂安·韦克

很好的信息。请允许我扩展现有的词典代码。谢谢。
Mike Malter

6

我认为这对于字典语义来说是过高的,因为字典从定义上来说是键及其各自值的集合,就像我们看到一本语言词典的方法一样,该书包含一个单词作为键,其描述性含义为值。

但是您可以表示一个可以包含值集合的字典,例如:

Dictionary<String,List<Customer>>

或者将键和值的字典作为字典:

Dictionary<Customer,Dictionary<Order,OrderDetail>>

然后,您将拥有一个可以包含多个值的字典。


1
一旦开始嵌套字典,您的代码就会开始看起来像多维数组。
IAbstract 2013年

@IAbstract在语义上不是那么相似。多维数组不关心键值的组合。同样,多维数组并不关心两个的最大元素(就像字典必须具有的一样)。
Eriawan Kusumawardhono

@eriawan:我不太清楚:) ...假定键的int值:myColl[0][1]...看起来多维数组。当您开始嵌套集合时,我相信是时候适当地封装“值”集合了。
IAbstract

@IAbstract很好!现在,我在您的最后评论中了解了您的观点。我同意我们应该正确封装值集合。
2013年

5

我认为您不能直接这样做。您可以创建一个同时包含object和的类,double然后将其实例放入字典中。

class Pair
{
    object obj;
    double dbl;
}

Dictionary<int, Pair> = new Dictionary<int, Pair>();

2

如果值是相关的,为什么不将它们封装在一个类中,而只使用普通的旧词典?


比对和元组更具可读性。什么是第一,第二,项目1,项目2?
KornMuffin 2013年

1

您描述了一个多图。

您可以将值设为List对象,以存储多个值(可扩展性大于2)。

覆盖字典对象。



1

我知道这是一个旧线程,但是-由于未提及,因此可以正常工作

  Dictionary<string, object> LookUp = new Dictionary<string, object>();
  LookUp.Add("bob", new { age = "23", height = "2.1m", weight = "110kg"});
  LookUp.Add("jasper", new { age = "33", height = "1.75m", weight = "90kg"});
  foreach(KeyValuePair<string, object> entry in LookUp )
  {
      object person = entry.Value;
      Console.WriteLine("Person name:" + entry.Key + " Age: "  + person.age);          
  }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.