tags:

views:

330

answers:

2

I am new to LINQ, I tried to run the following code and I got InvalidCastException error: "Unable to cast object of type 'd__3a`1[debug.Product]' to type 'debug.Product'" - what is wrong?

Code (VB - using VS2008)

    Private Sub btnLinq_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLinq.Click
        Dim Products As New List(Of Product)

        Dim p1 As New Product
        p1._ID = "1"
        p1._Name = "Product A"
        Products.Add(p1)

        Dim p2 As New Product
        p2._ID = "2"
        p2._Name = "Product B"
        Products.Add(p2)

        Dim p3 As New Product
        p3._ID = "3"
        p3._Name = "Product C"
        Products.Add(p3)

        Dim prod As Product = From p In Products Where p._ID = "1" Select p Take 1
        MsgBox(prod._ID)

    End Sub
End Class

Public Class Product
    Public _ID As String
    Public _Name As String
End Class
+4  A: 

Take returns an IEnumerable<Product> (in your case), and not a Product. (Check it by outputting result.GetType() ): (note that my example code is in C#)

        List<Product> products = new List<Product> ();

        products.Add (new Product ()
        {
            Id = 1,
            Name = "Prod1"
        });

        products.Add (new Product ()
        {
            Id = 2,
            Name = "Prod2"
        });


        var result = ( from p in products
                       where p.Id == 1
                       select p ).Take (1);

        Console.WriteLine (result.GetType ());

        Console.ReadLine ();

In my case, the code above outputs:

System.Linq.Enumerable+<TakeIterator>d__3a`1[LinqTest.Product]

In your case, instead of using Take 1, you could try to use First or FirstOrDefault instead.

So, try this:

        var result = ( from p in products
                       where p.Id == 1
                       select p ).FirstOrDefault ();

        Console.WriteLine (result.GetType ());
        Console.WriteLine (result.Name);
Frederik Gheysels
Thanks ... you were very helpful.
Avi
Then, you should mark the answer as accepted. :)
Frederik Gheysels
A: 

The Take method (Enumerable.Take) doesn't return an element, rather it returns an another sequence (IEnumerable<Product>). Take(n) just creates a new sequence with a maximum of n elements.

To take the first element from the sequence use one of the following methods:

  • FirstOrDefault() - returns null if the sequence is empty
  • First() - throws InvalidOperationException if the sequence is empty
Michael Damatov