user10607
user10607

Reputation: 3071

Can not cast IEnumerable<int> from LINQ to List<int> with .ToList()?

After reading this answer https://stackoverflow.com/a/902123 I wanted to check out how LINQ would work on multi-dimensional lists, so here is some test code that I just can not get right.

class Program
{
    static void Main(string[] args)
    {
        // Two dimensional list of ints
        var arr = new List<List<int>>();
        var rand = new Random();

        // fill the array with random values, this works fine.
        for (int i=0; i<10; i++)
        {
            arr.Add(new List<int>());
            for (int k=0; k<5; k++)
            {
                arr[i].Add( rand.Next(1, 21) );
            }
        }

        var q = from int e in arr select e;
        List<int> lst = q.ToList();  // This fails with InvalidCastException

        // here I would like to pretend that the list is one dimensional
        foreach (int i in lst)
        {
            Console.WriteLine(i);
        }
    }

The idea is that the list should look like it has only one dimension, after I cast the query back to List< int >.

What might be the cause of the problem:

Visual studio tells me that 'q' has type

{System.Linq.Enumerable.WhereSelectEnumerableIterator< int, int >}

Whereas the answer I linked to at the top of this question states that 'q' should have type

IEnumerable< int >

Question 1: Why is the exception thrown?

Question 2: How can I convert multi-dim list to one dimensional list with LINQ?

Thank you.

Upvotes: 0

Views: 4369

Answers (4)

Andrew
Andrew

Reputation: 1534

In you query from int e in arr select e You are trying to get int value from arg while each value of your arg is List<int>. Thats why you get InvalidCastException because it can not cast List<int> to int. If you want to get value from internal List<int> you can use query arg.Select(list => list).Select(val => val)

Upvotes: 0

Suren Srapyan
Suren Srapyan

Reputation: 68635

Answer 1:

I think like this:

var q = from int e in arr select e;

This is your code where your have wroten a query which will be executed later.

List<int> lst = q.ToList();

In this code you are calling your query to execute and then make .ToList().

Here you have declared a statement like this:

var arr = new List<List<int>>();

but in the query your trying to cast its content which is as List<int> to int,so this is why your are getting exception InvalidCastException. Your incorrect code is in

 var q = from int e in arr select e;

Here e is a List a your are trying to cast it to int and so you have your exception

Answer 2:

Change your code like this:

var q = from e in arr 
        from i in e select i;
List<int> lst = q.ToList();

Upvotes: 2

Siva Gopal
Siva Gopal

Reputation: 3502

Just modify your code as shown below and check if that work as you expected:

for (int i=0; i<10; i++)
{
     arr.Add(new List<int>());
     for (int k=0; k<5; k++)
     {
          arr[i].Add( rand.Next(1, 21) );
     }
}

//var q = from int e in arr select e; Remove this line
List<int> lst = arr.SelectMany(it=>it).ToList(); //This will flatten the result set

Upvotes: 0

Jenish Rabadiya
Jenish Rabadiya

Reputation: 6766

1. Why is the exception thrown?

    from e in arr select e;

instead of

    from int e in arr select e;

It was throwing exception because you were attempting to cast List<int> to int. More ever linq is smart enough to identify the type of variable do not specify it explicitly is recommended practices.

2. How can I convert multi-dim list to one dimensional list with LINQ?

make a use of selectMany method for above case.

    List<int> lst = q.SelectMany(d => d).ToList();

Here is .net fiddle for your reference.

Upvotes: 5

Related Questions