locked
C# Convert a LINQ query to a List<> RRS feed

  • Question

  • I can load records into  UpdateLoan class using method Update1. I was hoping to simplify the code like Update2 , but I keep getting this error.

    Instance argument: cannot convert from 'System.Linq.IQueryable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<UpdateLoan>'

    What LINQ principal have I missed?

    Thanks

      private class UpdateLoan
            {
                public string Loan_ID { get; set; }
            }
                  
            private void Upadate1()
            {
                List<UpdateLoan> Loans2Mark = new List<UpdateLoan>();
                var qryMk = dc.vu_ssi_GL_Trans_UnPosteds.Select(c => new { c.Loan_ID });
                foreach (var ln in qryMk)
                {
                    UpdateLoan rcd = new UpdateLoan();
                    rcd.Loan_ID = ln.Loan_ID;
                    Loans2Mark.Add(rcd);
                }
            }
            private void Update2()
            {
                List<UpdateLoan> Loans2Mark = new List<UpdateLoan>();
                var qryMk = dc.vu_ssi_GL_Trans_UnPosteds.Select(c => new { c.Loan_ID });
                Loans2Mark = qryMk.ToList<UpdateLoan>();
            }

    Tuesday, November 20, 2012 6:28 PM

Answers

  • Your query doesn't contain items that are "UpdateLoan" objects, it contains items that are of an anonymous type.  There is no implicit conversion between those two types.

    Rather than creating an anonymous type in the `Select` method you simply need to create an instance of UpdateLoan:

    List<UpdateLoan> Loans2Mark = dc.vu_ssi_GL_Trans_UnPosteds.Select(c =>
        new UpdateLoan
    {
        Loan_ID = c.Loan_ID
    })
    .ToList();

    Note that there's no sense in creating a blank list before the query; you're not adding items to that list, you're just throwing it away and assigning a new list to that variable.  No sense in doing that.  Also, you don't need to provide generic arguments to your `ToList` method in the vast majority of cases (in fact, I'd say you never should, personally).  If it's not compiling it means that the sequence really isn't of the correct type.  Adding the generic argument to `ToList` just hides that, and it'll fail at runtime.  You need to either use a `Cast` to explicitly indicate there is a valid cast, or convert the value (using , for example, `Select`) into something that's of the appropriate type.

    Tuesday, November 20, 2012 6:51 PM

All replies

  • Your query doesn't contain items that are "UpdateLoan" objects, it contains items that are of an anonymous type.  There is no implicit conversion between those two types.

    Rather than creating an anonymous type in the `Select` method you simply need to create an instance of UpdateLoan:

    List<UpdateLoan> Loans2Mark = dc.vu_ssi_GL_Trans_UnPosteds.Select(c =>
        new UpdateLoan
    {
        Loan_ID = c.Loan_ID
    })
    .ToList();

    Note that there's no sense in creating a blank list before the query; you're not adding items to that list, you're just throwing it away and assigning a new list to that variable.  No sense in doing that.  Also, you don't need to provide generic arguments to your `ToList` method in the vast majority of cases (in fact, I'd say you never should, personally).  If it's not compiling it means that the sequence really isn't of the correct type.  Adding the generic argument to `ToList` just hides that, and it'll fail at runtime.  You need to either use a `Cast` to explicitly indicate there is a valid cast, or convert the value (using , for example, `Select`) into something that's of the appropriate type.

    Tuesday, November 20, 2012 6:51 PM
  •  

    Fernando,

    I knew there had to be a more eloquent solution.

    Thanks,

    Ross

    Tuesday, November 20, 2012 7:37 PM
  • Also, you don't need to provide generic arguments to your `ToList` method in the vast majority of cases (in fact, I'd say you never should, personally).  If it's not compiling it means that the sequence really isn't of the correct type.  Adding the generic argument to `ToList` just hides that, and it'll fail at runtime.  You need to either use a `Cast` to explicitly indicate there is a valid cast, or convert the value (using , for example, `Select`) into something that's of the appropriate type.

    Calling ToList won't hide anything. SomeEnum.ToList<T>() will compile only if SomeEnum is convertible to IEnumerable<T>; that is, if SomeEnum's items are of type T or derived from T, or implement T. It will not fail at runtime.

    Calling Cast, on the other hand, will compile without warning and will fail at runtime if the items are not convertible.

    Wednesday, November 21, 2012 4:30 PM
  • Calling ToList won't hide anything. SomeEnum.ToList<T>() will compile only if SomeEnum is convertible to IEnumerable<T>; that is, if SomeEnum's items are of type T or derived from T, or implement T. It will not fail at runtime.

    Calling Cast, on the other hand, will compile without warning and will fail at runtime if the items are not convertible.

    You're correct; I didn't realize he was getting a compile time exception; I assumed he was already getting a runtime exception.  Still, the generic argument to `ToList` is entirely redundant 99% of the time.  Obviously `Cast` should only be used when you know that the underlying values are actually of the right type.
    Wednesday, November 21, 2012 4:43 PM
  • I would use Cast in only one case: if I have a non-generic IEnumerable.

    That's the equivalent of specifying the type in a query:

    from SomeType x in myEnum

    is translated as

    myEnum.Cast<SomeType>()

    I would use ToList with a type parameter any time I want a list of a base class or interface.

    • Edited by Louis.fr Wednesday, November 21, 2012 5:07 PM
    Wednesday, November 21, 2012 5:06 PM
  • I agree, except if you're willing to do something like myEnum.OfType<SomeOtherType>.Cast<SomeType>

    That way you're only applying that Cast to the objects that you know are able to be casted. Of course this could lead to other problems but I'm just pointing out that if you really need to use Case on a generic you can so long as you make sure it's of the type(s) you're expecting.

    Wednesday, November 21, 2012 6:39 PM