3

私は双方向の辞書クラスを作成して、どちらの方向でも高速に検索できるようにしています。

私のクラスは(部分的に)次のようになります。

public class DoubleDictionary<A,B>
{
    private Dictionary<A, B> _forward;
    private Dictionary<B, A> _backward;

    public A this[B b]
    {
        get { return _backward[b]; }
        set { _backward[b] = value; }
    }

    public B this[A a]
    {
        get { return _forward[a]; }
        set { _forward[a] = value; }
    }
}

この例では配列インデックス演算子を使用していますが、ほぼすべてのメソッドに 2 つのジェネリック バージョンがあります。A == Bの場合を除いて、うまく機能します。

私が行った場合

var foo = new DoubleDictionary<int, int>();
int x = foo[3];

あいまいなインデクサーのため、コンパイルさえしません。

コンパイラがこれに問題を抱えている理由を理解しており、おそらく合法ではないことに同意します。

が必要な有効なユースケースが実際にありDoubleDictionary<int,int>、配列インデックスがフォワード ディクショナリにアクセスすることを任意に選択したとします。

これらすべてを回避するために私がたどり着いた解決策は、方向ごとに一意に名前が付けられたメソッドの洗練されたインデックス作成構文を放棄することです。これにより、魔法がはるかに少なくなり、楽しくなくなります。

一意の名前のメソッドに頼ることなく、あいまいさを解決するためのヒントをコンパイラに与える方法はありますか? オーバーロードでこれを行うというアイデアが本当に好きで、そのままにしておきたいと思っています。呼び出し元が心配する必要がないようにクラスでそれを行うことをお勧めしますが、呼び出し元はそれを機能させるために何らかのリフレクション マジックを実行する必要があると思います。

それが不可能な場合は、A を B と同じにすることはできないという制限で問題ありません。宣言がDoubleDictionary<int,int>コンパイルされないように、それを成文化する方法はありますか? コンストラクターで例外をスローすることもできますが、コンパイル時にキャッチされるとよいでしょう。

4

3 に答える 3

3

2 つのインデクサーを使用することは、許可されたとしても非常に悪い設計です。

この辞書を持っている:

var foo = new DoubleDictionary<int, int>();
foo.Add(3, 4);
foo.Add(2, 3);

そして、次のことを行います:

foo[3]

あなたは2を得ると思いますか?または4?なぜ?

APIを明確にする方がよい。

于 2011-04-13T20:59:10.457 に答える
2

インデクサーはいつでも保持できますが、名前付きメソッドを補助APIとして追加します。おそらく拡張メソッドを使用して、usingディレクティブを追加することでそれらを機能させることができます...

于 2011-04-13T20:58:00.450 に答える
0

引数を指定できないインデクサーであり、汎用制約で型パラメーターを関連付ける唯一の方法は継承によることを考えると、あいまいさをそのまま解決する方法はありません。

GetKeyForValue(B value)良い妥協案は、前方ルックアップにインデクサーを使用し、後方ルックアップの方法のようなものを使用することだと思います。

于 2011-04-13T20:56:25.437 に答える