tags:

views:

94

answers:

3

I created some methods that use nested type parameters generic types in the parameter declaration:

public void Foo(IList<Pair<double, IList<double>>> myParameter)
{ // code goes here 
}

What I wanted to achieve was to force this method to accept 4 types of variables:

  • List<Pair<double, List<double>>> myVar
  • List<Pair<double, double[]>> myVar
  • Pair<double, List<double>>[] myVar
  • Pair<double, double[]>[] myVar

But it seems that second, nested interface cannot be converted on-the-fly by C#. While trying to pass some of variables listed above to my method, I get error:

Argument 1: Cannot convert from System.Collections.Generic.List<...> to Cannot convert from System.Collections.Generic.IList<...>

Do I really need to create two aliases for this method to handle this problem? Or maybe there is some kind of trick that I could use to overcome this problem?

+1  A: 

Without knowing what you are passing, the issue here is more than likely due to the fact that you don't have variance on generic type parameters.

Fortunately, in C# 4.0, this exists, and I'd be willing to guess that you could use IEnumerable<double> as the inner type parameter and it would work (unless you have a need to mutate the list as opposed to just iterating it.

If you are not able to use C# 4.0, then you are going to have to change the type parameter of your List<T> variable to the specific type requested.

casperOne
Thank you. Unfortunately, I cannot use C# 4.0 so probably I will have to create some aliases :/
Gacek
+3  A: 

Your code leads to a variance problem.

The inner IList<double> would allow you to assign List<double> even if you originally passed a double[], which would break type safety.

(This occurs fore the same reason as List<Orange> may not be treated as a List<Fruit>: You could push apples into it.)

In order to achieve correct variance behaviour, you'll have to ensure immutability as through the use of IEnumerable<T>s instead of IList<T>s (just works under .NET 4.0).

The previous versions of C# aren't able to handle variance at all!

Dario
Thanks for the simple explanation with fruits :) Now I understand what I was really trying to do ;)
Gacek
+2  A: 

You can use generic constraints in C# 2.0+

void Foo<TList>(IList<Pair<double, TList>> myParameter)
   where TList : IList<double>

C# has trouble with the type inference on this one though, so you will need to specify during calling.

Robert Davis
Thanks, it is some kind of solution but in the end it causes more trouble, than it is worth. Thanks anyway, for this try
Gacek
+1, but the `TList1` parameter is unnecessary here, which would simplify the signature and allow type inference to succeed in more cases.
kvb
Good point, code fixed.
Robert Davis