2010-10-26 48 views
1

我正在.NET 2.0框架中工作。我有一些代碼工作,只是希望它更加優雅一點。在通用方法中獲得更復雜類型的適當類型推斷

我有一個需要有效地「鏡子」 Dictionary對象,例如,如果我們有這樣的

Dictionary<TKey,TValue> StartDictionary; 

的對象開始,我們可以鏡像像這樣

Dictionary<TValue,TKey> MirroredDictionary = MirrorDictionary(StartDictionary); 

,我們將結束在每個KeyValuePair上都要交換一個新的字典,每個KeyValuePair都被交換。在任何人問我爲什麼之前,源字典相當大並且從re加載一次當我的程序加載時,flection調用。我不想再次運行相同的反射調用來加載鏡像字典。創建一個鏡像字典並按照我提出的方式填充它的值和密鑰在我看來似乎成本更低。

因此,作爲一種討厭重寫事物的人,我決定在助手類中編寫泛型方法,我必須使用泛型來完成鏡像。

現在想起你,我以前也寫過簡單的通用方法一般標量類型

這就是我想出了

public static TOutDic MirrorDictionary<TInDic, TOutDic>(TInDic InDictionary) 
    where TInDic : IDictionary 
    where TOutDic : IDictionary 
{ 
    Type[] KVPTypes = typeof(TInDic).GetGenericArguments(); 
    Type TKey = KVPTypes[0]; 
    Type TValue = KVPTypes[1]; 
    Type TDic = typeof(Dictionary<,>).MakeGenericType(TValue, TKey); 
    IDictionary OutDic = (IDictionary)Activator.CreateInstance(TDic); 
    foreach (DictionaryEntry DE in (IDictionary)InDictionary) OutDic.Add(DE.Value, DE.Key); 
    return (TOutDic)OutDic; 
} 

一點點的存在,但它的工作原理,加載了的類型鍵和值並創建鏡像字典的實例

然後只循環遍歷InDictionary的基本DictionaryEntries,它將項目添加到OutDic並返回它將其轉換爲預期的類型

編譯就好現在

當我去調用它,我會在我所說的通用方法,我可以只使用我們的代碼標量型覺得就像snippits上面說

Dictionary<TValue,TKey> MirroredDictionary = MirrorDictionary(StartDictionary); 

但是,不編譯給我

方法MirrorDictionary(TInDic)'的類型參數不能從用法推斷。嘗試明確指定類型參數。

所以,如果我把它而不是像這樣

 Dictionary<TValue, TKey> MirrorDic = MirrorDictionary<Dictionary<Tkey, TValue>, Dictionary<TValue,TKey>>(StringDic); 

它編譯和作品就像一個魅力。

現在的問題變成如何正確地推斷傳入此方法的類型時傳入的類型和傳出的類型是複雜的類型,如在此示例中?

+0

它如何可以推斷TOutDic當輸入參數僅供TInDic類型的信息? – 2010-10-26 17:27:20

回答

1

您可以讓生活更輕鬆編譯器通過告訴它的鍵和值類型如下:

public static Dictionary<TValue, TKey> MirrorDictionary<TKey, TValue> 
    (Dictionary<TKey, TValue> source) 
{ 
    Dictionary<TValue, TKey> destination = new Dictionary<TValue, TKey>(); 

    foreach (KeyValuePair<TKey, TValue> kvp in source) 
    { 
     destination.Add(kvp.Value, kvp.Key); 
    } 

    return destination; 
} 

我不認爲你需要在這裏反思。

使用範例:

static void Main(string[] args) 
{ 
    Dictionary<int, string> source = new Dictionary<int, string>(); 
    source.Add(3, "foo"); 
    source.Add(4, "bar"); 

    DumpDic(source); 

    DumpDic(MirrorDictionary(source)); 

    Console.ReadLine(); 

} 

其中DumpDic是:

public static void DumpDic<TK, TV>(Dictionary<TK, TV> dic) 
{ 
    foreach (KeyValuePair<TK, TV> keyValuePair in dic) 
    { 
     Console.WriteLine("{0} => {1}", keyValuePair.Key, keyValuePair.Value); 
    } 
} 
+0

我試過,首先它不會爲我編譯出於某種原因讓我回去重試它,也許當我第一次創建該方法時,我可能會搞砸了。我會在測試後重新發布 – TofuBug 2010-10-26 17:40:40

+0

Yep完全衝過方法聲明並忘記聲明我的類型,因此當我需要公共靜態字典時,公共靜態Dictionary MirrorDictionary(Dictionary InDictionary) MirrorDictionary (Dictionary InDictionary) – TofuBug 2010-10-26 17:46:58

0

您可以將Out字典定義爲out參數。類型推斷不會查看您要分配的變量的類型,而僅僅是參數的類型。這就是不能編譯的原因。

0

你需要告訴它TValue和TKey是什麼。除非它們在調用此代碼的方法的簽名中定義,否則它們沒有任何特定的類型。你需要給它的東西,如:

Dictionary<string, int> MirroredDictionary = MirrorDictionary(StartDictionary); 
+0

這不會幫助編譯器推斷TOutDic的類型,並且此行提供相同的編譯器錯誤。 – stevemegson 2010-10-26 17:40:16

+0

@stevemegson - 不,在進一步閱讀之後,它甚至沒有接近,我很想刪除它,但在我想讓它給別人留下評論的機會之後。 – 2010-10-26 17:44:31

+0

我會收回downvote然後,我只是懶得downvote,因爲單一upvote使它成爲當時的最佳答案。 – stevemegson 2010-10-26 17:52:05

1

這裏有一個3.5的解決方案

IDictionary<TValue, TKey> MirrorDictionary<TKey, TValue>(IDictionary<TKey, TValue> dict) 
{ 
    return dict.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); 
} 

和純2.0解決方案(你也可以在2.0與VS2008和LinqBridge使用它)

IDictionary<TValue, TKey> MirrorDictionary<TKey, TValue>(IDictionary<TKey, TValue> dict) 
{ 
    Dictionary<TValue, TKey> newDict = new Dictionary<TValue, TKey>(); 
    foreach(KeyValuePair<TKey, TValue> kvp in dict) 
    { 
     newDict.Add(kvp.Value, kvp.Key); 
    } 
    return newDict; 
} 

類型推斷應該對兩種解決方案都適用(因爲它們具有相同的簽名)

+0

除了避免反射外,這也強制輸入和輸出類型是正確的。沒有什麼可以阻止你將原始方法調用爲'MirrorDictionary ,Dictionary >(input)',它會很好地編譯,但在運行時會導致無效的轉換。 – stevemegson 2010-10-26 17:47:30