Q:

With C# 3.0, how to write Interface based code with generic collection?

I want to write code that is decouple and clean, and I know that by programming to an interface instead of the implementation, my code will be more flexible and extensible.  So, instead of writing methods like:
  bool IsProductAvailable(ProductTypeA product);

I write methods like:
  bool IsProductAvailable(IProduct product);

As long as my products implement IProduct:
  class ProductTypeA : IProduct

I should be OK.  All is well until I start using generic collections.  Since C# 3.0 doesn't support covariant and contravariant, even though both ProuctTypeA and ProductTypeB implements IProduct, you cannot put List in List.  This is pretty troublesome because a lot of times I want to write something like:
bool AreProductsAvailable(List<IProduct> products);

So that I can check product avaialbility by writing:
List<ProductA> productsArrived = GetDataFromDataabase();
bool result = AreProductsAvailable(productsArrived);

And I want to write just one AreProductsAvailable() method that works with all IProduct collections.
I know that C# 4.0 is going to support covariant and contravariant, but I also realize that there other libraries that seemed to have the problem solved.  For instance, I was trying out ILOG Gantt the gantt chart control, and found that they have a lot of collection intefaces that looks like this:
IActivityCollection
ILinkCollection 

So it seems like their approach is wrapping the generic collection with an interface.  So instead of "bool AreProductsAvailable(List products);", I can do:
bool AreProductsAvailable(IProductCollection products);

And then write some code so that IProductCollection takes whatever generic collection of IProduct, be it List or List.
However, I don't know how to write an IProductCollection interface that does that "magic".  :-<  (ashame) ....  
Could someone shed me some light?  This has been bugging me for so long, and I so wanted to do the "right thing".  Well, thanks!

A:

Even with .NET 4.0, List<T> won't be variant, for two reasons:

It's a class, not an interface or a delegate
It uses T in both input and output positions (which is why IList<T> isn't variant either in .NET 4.0)

One common solution to this problem is to add another type parameter:
bool AreProductsAvailable<T>(IList<T> products) where T : IProduct

You can then iterate through the list, accessing each element as just an IProduct - but the caller can use any compatible list type.

A:

How about AreProductsAvailable(IEnumerable<IProduct> products)?
Call it like this:
using System.Linq;

List<ProductTypeA> products = ...;
AreProductsAvailable(products.Cast<IProduct>());

