如何使用复合键创建字典?

6

我需要创建一个词典,其中键是枚举和整数的一对,值是对象。因此,我想将一对映射到某个对象。

其中一种选项是

public enum SomeEnum
{
 value1, value2
}

class Key
{
  public SomeEnum;
  public int counter;  

  // Do I have to implement Compare here?
}

Dictionary<SomeEnum, object> _myDictionary;

另一个选择是将枚举和整数转换为某个唯一键。
string key = String.Format("{0}/{1}", enumValue, intValue)

那种方法需要进行字符串解析,需要额外的大量工作。

如何让它更容易呢?


1
你使用的是哪个版本的C#? - Winston Smith
Visual Studio 2008,所以我认为它是3.5版本。 - Captain Comic
3个回答

9
我建议选择类似的方案。
public enum SomeEnum
{
 value1, value2
}

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

Dictionary<Key, object>

我认为这会使它变得更好吗?


是的,那绝对是最简单的 :) - leppie
字典如何比较两个键?它使用“==”还是IComparable? - Captain Comic
1
这是一个值类型,所以它只会执行 == 操作符。我不确定在32位系统上会怎样,但在64位系统上,我认为它只会比较两个内存位置,因为枚举和整数都可以放入64位中,这是一项廉价的操作。在32位系统上可能需要更多的指令吗? - Onkelborg
这种解决方案的优点是性能和简单性。比较起来很便宜。但是你无法控制排序,例如。 - Onkelborg
嗯,我想了想,你可以指定字段在内部存储的顺序。这应该允许您指定枚举和整数之间的内部关联。 - Onkelborg

9
如果您要将这个放入字典中,那么您需要确保实现一个有意义的.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;
    }
}

2
+1 提到.Equals和GetHashCode的陷阱。这是使用元组类型而不是自己编写简单键的好理由。 - Winston Smith
我相信结构体具有默认的GetHashCode和Equals覆盖,这将产生正确的结果,尽管默认的GetHashCode只是对结构体中的第一个元素进行哈希。如果大多数结构体在第一个元素上不同,则性能将很好,如果大多数结构体具有相同的第一个元素,则性能将非常差。 - supercat

7

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

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

1
是的,但这样就不太规范了——也就是说,没有描述键包含什么。但是,是可以实现的。 - Onkelborg
1
它是强类型的——键的类型为 Tuple<SomeEnum, int> - Winston Smith
1
因此,您的字典可以被定义为Dictionary<Tuple<SomeEnum, int>, object> - Winston Smith
1
是的,它是强类型的,但并不具描述性。如果您稍后获得该密钥,您知道那个整数实际上是什么吗?这就是我的观点。这可能是问题,也可能不是。这取决于情况 :) - Onkelborg
1
它是“强类型”,但不是“漂亮的类型”。使用struct(或匿名类型),您可以通过x.NameYouSpecify访问成员。使用元组,您访问x.Item1,这远不如前者信息丰富。 - Iain Galloway

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接