2011-04-13 48 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清晰。