1

コードを最適化するために、関数Indexerの独自のバージョンと独自のバージョンを作成しようとしています。これにより、 -likeクラス内で次のようなことができるようになります。FindEntryDictionary

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>Systementries

以下は、私が達成しようとしていることを示すのに役立つ、私のコードの基本的な例です。

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>有効ではないかもしれません。例えば:

  • 衝突はオープンアドレッシングによって解決されると想定しています。それらは、再ハッシュまたはチェーンによって同じように簡単に対処できます。
  • バケットの場所は、返されたハッシュコードをバケットの数で割ることによって計算されると想定しています。他の可能性があります。
  • これらの2つの仮定が正しいことが証明されたとしても、実装は将来変更されず、以前の仮定が無効になると想定しています。

また、基本クラスの内部データ構造にアクセスできることを前提としていますが、これは不可能です。私の知る限り、クラスの保護されたインターフェイスbucketsには配列がありません。Dictionary

あなたが投稿したものから、あなたの仮定が正しければ、あなたが節約する唯一の実行時間は、各アイテムのハッシュコードを計算するのに費やされた時間であるように思われます。これは、アイテムを作成するとき(つまり、コンストラクターで)にアイテムのハッシュコードを計算し、それをキャッシュすることで簡単に解決できます。したがって、あなたのGetHashCode方法はただですreturn this.cachedHashCode;

もちろん、これは、辞書に配置する項目が不変であることを前提としています。または、少なくとも、同等性を判断するために使用されるフィールドは不変です。

そして最後に、それがDictionaryプログラムのパフォーマンスを制限する要因であると確信していますか?そうでなければ、おそらくあなたの最適化の努力は他の場所でよりよく使われるでしょう。

于 2012-12-27T19:06:22.443 に答える
0

ジムとジョンは正しく、あなたの問題の解決策は簡単だと思います。

に変更しGetHashCodeて、db番号、「-」、およびユーザー番号を連結し、その文字列でベースGetHashCodeを呼び出します。

このようにして、本番環境とデバッグで実装を変更する必要はありません。

于 2012-12-28T00:55:04.047 に答える