避免使用泛型类型的模糊调用错误

时间:2011-04-13 20:46:46

标签: c# generics overload-resolution

我有一个双向字典类,允许我在任一方向快速查找。

我的班级(部分)看起来像这样:

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>的声明不会编译?我可以在构造函数中抛出一个异常,但如果在编译时捕获它会很好。

3 个答案:

答案 0 :(得分:3)

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

有这本词典:

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

然后做:

foo[3]
你希望得到2吗?还是4?为什么?

更好地使API清晰。

答案 1 :(得分:2)

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

答案 2 :(得分:0)

没有任何方法可以解决模糊性,因为它是一个不允许您指定参数的索引器,并且通用约束中关联类型参数的唯一方法是继承。

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