Gacek
Gacek

Reputation: 10322

Nested generic type parameters - how to handle it?

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:

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?

Upvotes: 2

Views: 4862

Answers (3)

Robert Davis
Robert Davis

Reputation: 2265

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.

Upvotes: 2

Dario
Dario

Reputation: 49218

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!

Upvotes: 5

casperOne
casperOne

Reputation: 74560

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.

Upvotes: 1

Related Questions