使用C#3.0,如何使用泛型集合编写基于接口的代码?

Dee*_*cay 2 c# generics collections

我想编写解密和干净的代码,我知道通过编程到接口而不是实现,我的代码将更灵活和可扩展.所以,而不是写如下方法:

  bool IsProductAvailable(ProductTypeA product);
Run Code Online (Sandbox Code Playgroud)

我写的方法如下:

  bool IsProductAvailable(IProduct product);
Run Code Online (Sandbox Code Playgroud)

只要我的产品实现IP产品:

  class ProductTypeA : IProduct
Run Code Online (Sandbox Code Playgroud)

我应该没事.一切顺利,直到我开始使用泛型集合.由于C#3.0不支持协变和逆变,即使ProuctTypeA和ProductTypeB都实现了IProduct,也不能将List放入List中.这很麻烦,因为很多时候我想写一些类似的东西:

bool AreProductsAvailable(List<IProduct> products);
Run Code Online (Sandbox Code Playgroud)

这样我就可以通过以下方式检查产品的可用性:

List<ProductA> productsArrived = GetDataFromDataabase();
bool result = AreProductsAvailable(productsArrived);
Run Code Online (Sandbox Code Playgroud)

我想只编写一个适用于所有IProduct集合的AreProductsAvailable()方法.

我知道C#4.0将支持协变和逆变,但我也意识到其他库似乎已经解决了问题.例如,我正在尝试ILOG Gantt甘特图控件,并发现他们有很多集合接口,如下所示:

IActivityCollection
ILinkCollection 
Run Code Online (Sandbox Code Playgroud)

所以看起来他们的方法是使用接口包装泛型集合.因此,我可以这样做,而不是"bool AreProductsAvailable(List products);"

bool AreProductsAvailable(IProductCollection products);
Run Code Online (Sandbox Code Playgroud)

然后编写一些代码,以便IProductCollection获取IProduct的任何通用集合,无论是List还是List.

但是,我不知道如何编写一个"魔术"的IProductCollection接口.: - <(ashame)....

有人能给我一些光明吗?这已经困扰了我很久了,我也想做"正确的事".非常感谢!

Jon*_*eet 6

即使使用.NET 4.0,List<T>也不会有变体,原因有两个:

  • 它是一个类,而不是接口或委托
  • 它用于T输入和输出位置(这就是为什么IList<T>在.NET 4.0中没有变体)

此问题的一个常见解决方案是添加另一个类型参数:

bool AreProductsAvailable<T>(IList<T> products) where T : IProduct
Run Code Online (Sandbox Code Playgroud)

然后,您可以遍历列表,只访问每个元素IProduct- 但调用者可以使用任何兼容的列表类型.