Home > Blockchain >  Cannot implicitly convert type List<List<T>> to IList<IList<T>>
Cannot implicitly convert type List<List<T>> to IList<IList<T>>

Time:05-03

I'm working on some problems on Leetcode and coding in C#, and problems which require a collection of collections require a return type of IList<IList<<int>>.

I am failing to understand why I get the following error, when I return a type of List<List<int>> :

error CS0266: Cannot implicitly convert type 'System.Collections.Generic.List<System.Collections.Generic.List>' to 'System.Collections.Generic.IList<System.Collections.Generic.IList>'. An explicit conversion exists (are you missing a cast?) (in Solution.cs)

List<T> implements IList<T>...so why is it that I am getting such errors?

I've also tried instantiating an IList<List<T>> and I get the same type of error as well. I'm genuinely confused. It seems there is something that I am failing to understand correctly about the type parameters for this generic type.

CodePudding user response:

If you have a list

List<List<int>> listOfLists = new List<List<int>>();

and you have some IList<int> someList

you can't do this

listOfLists.Add(someList);

because listOfLists is expecting List<int> as an input. Basically you can implicitly convert List<int> to IList<int> for output, but you can't implicitly convert IList<int> to List<int> for input

What you can do is just define your original list as IList<IList<int>>

IList<IList<int>> listOfLists = new List<IList<int>>();

and you can add List<int> or IList<int> to that list and return it matching your required output.

CodePudding user response:

The way how type arguments of generics work is sometimes counterintuitive and different from language to language.

Suppose that you have a generic type G<T> and two types A and A1. Now, supposing that A1 derives from A, this does not imply that G<A1> is a subtype of G<A>!

The reason behind this is a type safety concept called variance and, for this particular case, invariance. In simple words, the only subtype of G<A> is G<A> itself.

To relate the general rule above to your scenario, G<T> is IList<T> (the outer one), A is IList<int> (the inner one) and A1 is List<int>.

To solve your issue, instead of declaring and IList<List<T>> as you said in the last paragraph of your question, you may declare and return a List<IList<T>> (note: swapped with respect to your declaration) or even directly a IList<IList<T>>.

Finally, keep in mind that, even if the error message talks about a missing cast, there should be no need for any casts and everything can be solved type-safely.

If you could provide the snippet that has the error, I can point out more concretely where the issue is and what's the cleanest solution.

  • Related