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

Elr*_*ynn 10 .net c# dictionary key

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

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

Dictionary<int, Dictionary<int, Data>>  myData;
Run Code Online (Sandbox Code Playgroud)

所以查找可以像这样编码:

Data data1  = myData[itemId][regionId];
Run Code Online (Sandbox Code Playgroud)

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

Data data1 = null;
if (myData.ContainsKey(itemId)) data1 =  myData[itemId][regionId];
Run Code Online (Sandbox Code Playgroud)

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

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

Dictionary<MultiPartKey, Data>  myData;
Run Code Online (Sandbox Code Playgroud)

并且查找将是:

MultiPartKey mpk;
mpk.ItemId = itemId;
mpk.RegionId = regionId;
Data data1 = myData[mpk];
Run Code Online (Sandbox Code Playgroud)

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

你怎么看?

Jon*_*eet 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Cod*_*odo 11

另一种方法是使用Tuple类:

Dictionary<Tuple<int, int>, Data>  myData;
Run Code Online (Sandbox Code Playgroud)

如果它们实现EqualsGetHashCode,则最多可以使用八个值.