2011-04-13 77 views
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]; 

它甚至不会编译,因为不明确的索引的。

我明白为什么编译器有这个问题,我同意它可能不合法。

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

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

有什么办法可以让编译器提示解决歧义而不必求助于唯一命名的方法吗?我真的很喜欢这种重载的想法,并希望保持这种状态。我更喜欢在课堂上这样做,因此调用者不必担心它,但我想象调用者将不得不做一些反射魔术来使其工作。

如果它不可能,我会保持克制,以便A不能与B相同。有没有什么方法可以编码,以便DoubleDictionary<int,int>的声明不会编译?我可以在构造函数中抛出一个异常,但如果它在编译时被捕获,它会很好。

+5

“这使得它变得更加神奇,而且更加有趣。”我认为它会改进设计并使API更清晰。 – 2011-04-13 20:50:00

+0

公平的一点。我仍然喜欢数组索引,因为它更像是Dictionary类的索引,它非常简洁。 – captncraig 2011-04-13 20:52:28

回答

2

您可以始终保持索引,但增加了一个名为方法作为辅助API - 甚至可以通过扩展方法,也许这样你就可以通过添加using指令发挥他们......

+0

这似乎非常明智。当我明白发生了什么时,我会得到魔法,但是当我需要它时,还有一个更明确的模式。听起来不错。 – captncraig 2011-04-13 21:01:53

0

由于它是一个索引器,不允许您指定参数,并且在泛型约束中关联类型参数的唯一方法是继承,所以没有任何方法可以解决歧义性问题。

我认为一个很好的折衷办法是使用索引器进行前瞻性查找,并使用GetKeyForValue(B value)方法进行反向查找。

3

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

有了这本字典:

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

,然后做:

foo[3] 

,你会期望得到2?或4?为什么?

更好地使API清晰。