【问题标题】:How to use compound key for dictionary?如何在字典中使用复合键?
【发布时间】:2010-10-20 09:06:11
【问题描述】:

我需要安排一种字典,其中键是一对 enum 和 int 价值是对象。所以我想将一对映射到某个对象。

一个选项是

public enum SomeEnum
{
 value1, value2
}

class Key
{
  public SomeEnum;
  public int counter;  

  // Do I have to implement Compare here?
}

Dictionary<SomeEnum, object> _myDictionary;

另一种选择是将 enum 和 int 转换为某个唯一键。

string key = String.Format("{0}/{1}", enumValue, intValue)

这种方法需要进行字符串解析,需要做很多额外的工作。

如何轻松搞定?

【问题讨论】:

  • 你使用的是什么版本的 C#?
  • Visual Studio 2008 所以我认为它是 3.5

标签: c# .net generics dictionary


【解决方案1】:

我会选择类似的东西

public enum SomeEnum
{
 value1, value2
}

public struct Key
{
  public SomeEnum;
  public int counter;  
}

Dictionary<Key, object>

我觉得这样可以吗?

【讨论】:

  • 是的,这是迄今为止最简单的:)
  • Dictionary 如何比较两个键?它使用 == 还是 IComparable?
  • 它是一个值类型,所以它只会执行一个==。我不确定 32 位系统,但在 64 位系统上,我认为它只会比较两个内存位置,因为 enum 和 int 将适合 64 位,这是一个便宜的操作。在 32 位上,它可能(?)需要更多指令?
  • 此解决方案的优势在于性能和简单性。比较便宜。但是你不能控制排序,例如
  • 嗯,当我想到它时,您可以指定字段在内部存储的顺序。这应该允许您指定枚举和 int 之间的内部相关性
【解决方案2】:

如果要将其放入字典中,则需要确保实现有意义的.Equals.GetHashCode,否则字典将无法正常运行。

我会从下面的基本复合键开始,然后实现一个自定义 IComparer 以获得您需要的排序顺序。

public class MyKey
{
    private readonly SomeEnum enumeration;
    private readonly int number;

    public MyKey(SomeEnum enumeration, int number)
    {
        this.enumeration = enumeration;
        this.number = number;
    }

    public int Number
    {
        get { return number; }
    }

    public SomeEnum Enumeration
    {
        get { return enumeration; }
    }

    public override int GetHashCode()
    {
        int hash = 23 * 37 + this.enumeration.GetHashCode();
        hash = hash * 37 + this.number.GetHashCode();

        return hash;
    }

    public override bool Equals(object obj)
    {
        var supplied = obj as MyKey;
        if (supplied == null)
        {
            return false;
        }

        if (supplied.enumeration != this.enumeration)
        {
            return false;
        }

        if (supplied.number != this.number)
        {
            return false;
        }

        return true;
    }
}

【讨论】:

  • +1 用于提及 .Equals 和 GetHashCode 问题。这是使用 Tuple 类型而不是滚动您自己的简单键的一个很好的理由。
  • 我相信结构具有 GetHashCode 和 Equals 的默认覆盖,这将产生正确的结果,尽管默认的 GetHashCode 只是散列结构中的第一个元素。如果大多数结构的第一个元素不同,性能会很好,如果大多数结构的第一个元素相同,性能就会很差。
【解决方案3】:

如果您使用的是 C# 4.0,则可以使用 Tuple 类。

var key = Tuple.Create(SomeEnum.Value1, 3);

【讨论】:

  • 是的,但是它没有很好地键入 - 即没有描述密钥的组成部分。但是,是的,这是可能的
  • 它是强类型的——密钥是Tuple&lt;SomeEnum, int&gt;类型的。
  • 所以你的字典可以定义为Dictionary&lt;Tuple&lt;SomeEnum, int&gt;, object&gt;
  • 是的,它是强类型的,但它不是描述性的。如果你以后得到那个键,你知道那个整数到底是什么吗?这就是我的观点。这可能是也可能不是问题。这取决于:)
  • 它是“强类型”,但不是“好类型”。使用结构(或匿名类型),您可以通过 x.NameYouSpecify 访问成员。使用元组,您可以访问 x.Item1,这远没有提供丰富的信息。
猜你喜欢
  • 2011-02-22
  • 2013-01-28
  • 2018-03-27
  • 2021-08-29
  • 2014-09-23
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 2020-11-08
相关资源
最近更新 更多