多部分int字典键的最佳方法?

时间:2011-02-11 21:58:47

标签: c# .net dictionary key

假设我的字典需要由ItemId和RegionId的组合键入,两者都是int。并且说值侧的类型是“数据”。 我可以通过以下两种方式做到这一点:

方式1:多级字典,如下所示:

Dictionary<int, Dictionary<int, Data>>  myData;

所以查找可以这样编码:

Data data1  = myData[itemId][regionId];

不错,但缺点是我需要在第一级检查密钥是否存在,因此更安全的代码将是

Data data1 = null;
if (myData.ContainsKey(itemId)) data1 =  myData[itemId][regionId];

方式2:使用多部分密钥。 在这种方法中,我将创建一个表示部件的结构,并使用结构作为字典键:

private struct MultiPartKey
{
    public int ItemId;
    public int RegionId;
}

Dictionary<MultiPartKey, Data>  myData;

,查找就像:

MultiPartKey mpk;
mpk.ItemId = itemId;
mpk.RegionId = regionId;
Data data1 = myData[mpk];

这里可能的缺点是它只有在我的结构完全由简单值类型组成时才有效,因此两个实例的按位比较将是相等的。 (右?)

您怎么看?

2 个答案:

答案 0 :(得分:19)

不要让你的结构像这样“哑”(并且可变),你可以使它成为不可变的并给它适当的相等方法,例如。

private struct MultiPartKey : IEquatable<MultiPartKey>
{
    private readonly int itemId;
    private readonly int regionId;

    public int ItemId { get { return itemId; } }
    public int RegionId { get { return regionId; } }

    public MultiPartKey(int itemId, int regionId)
    {
        this.itemId = itemId;
        this.regionId = regionId;
    }

    public override int GetHashCode()
    {
        int hash = 17;
        hash = hash * 31 + itemId;
        hash = hash * 31 + regionId;
        return hash;
    }

    public override bool Equals(object other)
    {
        return other is MultiPartKey ? Equals((MultiPartKey)other) : false;
    }

    public bool Equals(MultiPartKey other)
    {
        return itemId == other.itemId &&
               regionId == other.regionId;
    }
}

您可以扩展它以使用您想要的任何类型,只要您正确实现相等和哈希代码。实现IEquatable<MultiPartKey>意味着字典不需要打包密钥以便比较它们。

使用此方法而不是Dictionary<int, Dictionary<int, Data>>的缺点是您无法轻松找到给定商品ID的所有条目。

答案 1 :(得分:11)

另一种方法是使用 Tuple 类:

Dictionary<Tuple<int, int>, Data>  myData;

如果它们实现 Equals GetHashCode ,则最多可以使用八个值。