2016-07-28 19 views
1

我試圖在我的一種方法中靈活使用IDictionary接口,但由於轉換限制(請參閱C# type conversion: Explicit cast exists but throws a conversion error?),它的使用對我來說非常有限。我想知道是否有一些解決方法。靈活使用IDictionary(帶接口)

這是我的具體問題: 我有一個方法,它採用映射將每個鍵映射到其他鍵的IEnumerable。它也需要一個鍵作爲輸入。它所做的是找到關於映射給定鍵的封閉套/殼:

public static ISet<T> GetClosureSet(T element, IDictionary<T, IEnumerable<T>> elementToCollectionMap) 
{ 
    ISet<T> closure = new HashSet<T>(); 
    closure.Add(element); 
    closure.UnionWith(elementToCollectionMap[element]); 

    int count = 0; 
    while (count != closure.Count) 
    { 
     count = closure.Count; 
     foreach (T elem in new HashSet<T>(closure)) 
      closure.UnionWith(elementToCollectionMap[elem]); 
    } 

    return closure; 
} 

IDictionary<double, IEnumerable<double>>類型的這種映射的例子:

1 -> [2, 3, 4] 
2 -> [3, 7] 
3 -> [3] 
4 -> [] // empty enumerable, i.e. array of length 0 
5 -> [6] 
6 -> [6] 
7 -> [] 

如果我把鑰匙1這映射到我的方法,我會得到[1, 2, 3, 4, 7]:第一個1和它的圖像[2, 3, 4]放在一起到閉集。然後添加1,2,3,4的圖像,所以我們也獲得7(作爲2圖像的元素)。在下一步中,所有1,2,3, ,4,7的圖像都被添加,但它們已經在那裏。因此,該方法結束並返回。

正如你所看到的,這是一個非常抽象的方法,不關心值的真正含義。它只需要值爲IEnumerable<T>即可致電UnionWith

但是現在我希望能夠使用該方法,只要我有一個從鍵到某種鍵集合的映射!

我有我的代碼中的一些地方,我定義

IDictionary<MyType, HashSet<MyType>> foo = new Dictionary<MyType, HashSet<MyType>>(); 

IDictionary<MyType, List<MyType>> bar = new Dictionary<MyType, List<MyType>>(); 

,並需要他們真正IDictionary<MyType, HashSet<MyType>>IDictionary<MyType, List<MyType>>因爲我需要的HashSetList比其他一些功能由IEnumerable提供。後來我纔想要關閉。但現在,我不能給foobar作爲我的方法的輸入 - 我需要從它們創建新詞典來適應類型。

關於如何解決問題的任何想法(我不認爲「創建一個適合類型的新字典」的解決方案)?

回答

2

解決此問題的最佳方法是對公共API進行輕微更改。從根本上說GetClosureSet並不需要所有鍵該鍵值序列的映射,只需要一個操作以獲取所有的值對於給定的關鍵:

public static ISet<T> GetClosureSet(
    T element, 
    Func<T, IEnumerable<T>> childSelector) 

呼叫者可以實現方法任何方式,其中之一是在他們的字典中執行查找。這實際上使得您的方法更具有普遍性,因爲它允許您在不同類型的圖表上執行此操作,這些圖表完全不同地存儲它們的節點,例如「節點」對象,每個對象都有一個對一組子對象的引用比存儲在字典中的圖更好。

+0

Can'Funct '對於類型'T'的某些輸入具有「無價值」,就像'Dictionary'一樣嗎? – Kjara

+1

@Kjara如果一個對象沒有映射,那麼該選擇器應該返回一個空序列。鑑於你的字典已經存儲了一個空序列作爲該鍵的值,調用者只需要寫'element => foo [element]'。當然,如果一個不同的調用者完全將其圖形存儲在不同的莊園中,他們可能會以不同的方式調用它。 – Servy

+0

而且'Func '爲空? (只是檢查我是否必須更改我的代碼中有關無效輸入的任何內容。) – Kjara

2

您可以添加參數集合類型:

public static ISet<T> GetClosureSet<T, C>(T element, IDictionary<T, C> elementToCollectionMap) where C : IEnumerable<T> { ... } 

注意編譯器將無法推斷C你。