2011-04-07 47 views
4

在一個用於內部可重用庫的通用C#類中,我想傳遞一個對「映射到其他東西列表的東西」的引用。圖書館不應該知道傳入的數據類型。而且,它們的存儲方式也不應該被知道,也就是說今天的什麼是存儲在內存中的列表,以後可能是一個數據庫表,它可以根據需要讀取。用IDictionary和IEnumerable嵌套泛型

所以我想我會寫這個庫類:

class GenericClass<T, U> 
{ 
    public void Foo(IDictionary<T, IEnumerable<U>> bar) 
    { 
     // do something 
    } 
} 

這編譯,但試圖具體實現通過不:

class UsingClass 
{ 
    public static void Main(string[] args) 
    { 
     var c = new GenericClass<string, string>(); 
     c.Foo(new Dictionary<string, List<string>>()); 
    } 
} 

我得到了以下兩個語法錯誤:

Filename.cs(46,13): error CS1502: The best overloaded method match for 'GenericClass<string,string>.Foo(System.Collections.Generic.IDictionary<string,System.Collections.Generic.IEnumerable<string>>)' has some invalid arguments 
Filename.cs(46,19): error CS1503: Argument 1: cannot convert from 'System.Collections.Generic.Dictionary<string,System.Collections.Generic.List<string>>' to 'System.Collections.Generic.IDictionary<string,System.Collections.Generic.IEnumerable<string>>' 

在的聲明中替換與List修復它,但這當然不是我想要的。

這真的不是由C#(4.0)支持,還是我只是錯過了明顯的東西?你會建議什麼解決方法? (我確定這已經被討論過很多,所以很好的描述的鏈接也很好。)

是的,我應該能夠爲我寫自己的幫助類,但爲什麼我必須?

回答

8

是的,這真的不被支持。想象一下你的Foo方法看起來像這樣:

public void Foo(IDictionary<T, IEnumerable<U>> bar) 
{ 
    T key = GetKeyFromSomewhere(); 
    bar[key] = new U[10]; // Create an array 
} 

這看起來不錯,不是嗎?我們可以從U[]轉換爲IEnumerable<U>

雖然從調用者的角度來看它並不是很好 - 突然我們在字典中得到了string[]參考值,當所有的值都是List<string>引用! Bang的類型安全。

您可以重寫方法:

public void Foo<TValue>(IDictionary<T, TValue> bar) 
    where TValue : IEnumerable<U> 

這將讓你獲得價值出字典並將其轉換爲IEnumerable<U>隱...但你只能夠把完全正確類型的值分成字典,並且不能僅根據U值建立。

從版本4開始,C#在受限制的情況下支持通用方差。因此,例如,這種(針對.NET 4時),但以前工作在C#4不會:

List<string> strings = new List<string>(); 
IEnumerable<object> objects = strings; 

對於很多更多的通用方差,看Eric Lippert's blog series的話題。準備好讓你的大腦定期爆炸。

+0

呃,我不知道我是否同意。對於調用者實際上有問題的情況,他們必須假設他們將從字典中找回'List ',當該函數只承諾'IEnumerable '時。 – siride 2011-04-07 16:52:54

+0

@siride:但是調用者已經通過'Dictionary >'。該類型保證具有始終與'List '兼容的值。如果該方法試圖將錯誤的值放入該字典中,那麼*真的,真的*應該以某種方式發生爆炸,理想情況是在編譯時。或者您不認爲泛型集合中的類型安全性很重要嗎? ;) – 2011-04-07 16:54:45

+0

無論如何,這正是我正在尋找和我的代碼編譯和現在按預期工作。謝謝,喬恩! – 2011-04-07 16:56:32