1

为了优化我的代码,我正在尝试创建我自己Indexer和我自己的FindEntry函数版本 - 这样我就可以在Dictionary-like 类中执行以下操作:

object IDictionary.this[int key] {
    get {
        int num = this.FindEntry(key);
        if (num >= 0) {
            return this.entries[num].value;                 
        }

        return null;
    }

    set {
        Dictionary<TKey, TValue>.VerifyValueType(value);
        this [key] = (TValue)((object)value);
    }
}

private int FindEntry (int key) {
    if (this.buckets != null) {
        int num = key & 2147483647;
        for (int i = this.buckets[num % this.buckets.Length]; i >= 0; i = this.entries[i].next) {
            if (this.entries[i].hashCode == num && this.comparer.Equals(this.entries[i].key, key)) {
                return i;
            }
        }
    }
    return -1;
}

这很有用,因为我的字典的键是一个结构 - 但有时我有哈希码而不是键。

我正在寻找除了重写Dictionary<TKey, TValue>之外的解决方案System- 但我怀疑这可能是唯一的方法,因为其中的变量entries是私有的。

下面是我的代码的一个基本示例,以帮助展示我想要完成的工作。

struct SuperKey : IEquatable<SuperKey> {
    public int Id;
    public int Environment;

    public override int GetHashCode() {
        return this.Id;
    }

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

    public bool Equals(SuperKey other) {
        return this.Id == other.Id && this.Environment == other.Environment;
    }
}

class Example {
    Dictionary<SuperKey, Player> players;

    void MyFunction() {
        SuperKey sk = new SuperKey(36, 1);
        Player p1 = new Player();

        players.Add(sk, p1);
    }

    void ReceiveEventForPlayer(int id, PlayerEventName name) {
        ReceiveEventForPlayer(id, 0, name);
    }

    void ReceiveEventForPlayer(int id, int environment, PlayerEventName name) {
        Player p = players[new SuperKey(id, 1)];
    }

}

ReceiveEventForPlayer上面的方法中,请注意以下行:

Player p = players[new SuperKey(id, 1)];

我更希望能够使用:

Player p = players[id];

但这不起作用......实际上能够使用任何一种语法都是最理想的。

4

2 回答 2

1

您对Dictionary<TKey, TValue>可能无效的实施做出了很多假设。例如:

  • 您假设通过开放寻址解决冲突。它们可以很容易地通过重新散列或链接来解决。
  • 您假设存储桶位置是通过将返回的哈希码除以存储桶数量来计算的。还有其他可能性。
  • 即使这两个假设被证明是正确的,您也假设实现在未来不会改变并且使您之前的假设无效。

您还假设您可以访问基类的内部数据结构,这是不可能的。据我所知,类的受保护接口buckets中没有数组。Dictionary

从您发布的内容来看,如果您的假设正确,您似乎唯一可以节省的执行时间就是计算每个项目的哈希码所花费的时间。这很容易通过在创建项目时计算项目的哈希码(即在构造函数中)并缓存它来解决。那么,你的GetHashCode方法就是return this.cachedHashCode;

当然,这假设您放入字典中的项目是不可变的。或者,至少,任何用于确定相等性的字段都是不可变的。

最后,您确定这Dictionary是您程序性能的限制因素吗?如果没有,也许您的优化工作最好花在其他地方。

于 2012-12-27T19:06:22.443 回答
0

Jim 和 Jon 是正确的,我认为解决问题的方法很简单:

只需更改为GetHashCode将数据库编号、“-”和用户编号连接起来,然后在该字符串上调用基本 GetHashCode。

通过这种方式,您不必更改生产和调试中的实现。

于 2012-12-28T00:55:04.047 回答