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; }
    }
}

我在这个例子中使用了数组索引运算符,但几乎每个方法都有两个通用版本。除了A == B 的情况外,它工作得很好。

如果我做

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

由于索引器不明确,它甚至无法编译。

我理解为什么编译器对此有问题,并且我同意它可能不合法。

假设我实际上有一个需要 a 的有效用例DoubleDictionary<int,int>,并且我任意选择数组索引应该访问正向字典。

我为解决所有这些问题而得出的解决方案是为每个方向的唯一命名方法放弃光滑的索引语法。这使它变得不那么神奇,也不那么有趣。

有没有办法给编译器提示来解决歧义,而不必求助于唯一命名的方法?我真的很喜欢用重载来做这个的想法,并希望保持这种状态。我宁愿在课堂上这样做,这样调用者就不必担心它,但我想调用者必须做某种反射魔法才能让它工作。

如果不可能的话,我会很好地限制 A 不能与 B 相同。有没有办法对此进行编码,以便声明DoubleDictionary<int,int>不会编译?我可以在构造函数中抛出异常,但如果它在编译时被捕获就更好了。

4

3 回答 3

3

好吧,如果允许的话,拥有两个索引器将是一个非常糟糕的设计。

有这本词典:

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

using您始终可以保留索引器,但将命名方法添加为辅助 API - 甚至可以通过扩展方法,以便您可以通过添加指令来发挥它们的作用......

于 2011-04-13T20:58:00.450 回答
0

没有任何方法可以按原样解决歧义,因为它是一个不允许您指定参数的索引器,并且在泛型约束中关联类型参数的唯一方法是通过继承。

我认为一个很好的折衷方案是使用索引器进行前向查找和类似的GetKeyForValue(B value)向后查找方法。

于 2011-04-13T20:56:25.437 回答