-1

I have a list of objects List<Student> that I want return as an IQueryable<Student>.

When I try to use .AsQueryable() on the list to convert it to IQueryable<Student> I got a System.Collections.Generic.List`1[ConsoleApp.Student].

How I can convert list to IQueryable()?

See below I minimum reproducible example:

using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            var students = new List<Student>() ;
            students.Add(new Student() { Id = 1, Name = "J" });
            students.Add(new Student() { Id = 2, Name = "X" });

            IQueryable<Student> queryable = students.AsQueryable();

            Console.WriteLine("Hello, World!");
        }
    }
}
GSerg
  • 76,472
  • 17
  • 159
  • 346
gvd
  • 1,482
  • 6
  • 32
  • 58
  • 1
    Isn't iqueryable an interface? you can't have that by itself -- just things that implement it. – Hogan Jan 19 '23 at 16:01
  • https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interface – Hogan Jan 19 '23 at 16:01
  • Can you please elaborate on _"I got a {System.Collections.Generic.List`1[ConsoleApp.Student]}"_? – Guru Stron Jan 19 '23 at 16:03
  • 2
    "When I try to use .AsQueryable() on the list to convert it to IQueryable I got a System.Collections.Generic.List`1[ConsoleApp.Student]." And how did you determine that? When I changed your code to output `queryable.GetType()` instead of "Hello World" it printed `System.Linq.EnumerableQuery`1[ConsoleApp.Student]` – Jon Skeet Jan 19 '23 at 16:03
  • Maybe you just need `.ProjectTo`? With EF Core it will produce `IQueryable`. For the future questions, do not strip problem details, everything counts. EF Core is very strict for querying. – Svyatoslav Danyliv Jan 19 '23 at 17:47

1 Answers1

3

.AsQueryable() returns a EnumerableQuery<T> that wraps the list (or IEnumerable<T> to be precise) and provides the IQueryable interface. So if you just want an IQueryable<T> your don't need to do anything more. Your example already demonstrates this perfectly well.

Note that, the .ToString()-method on EnumerableQuery just seem to call the underlying collection, so it will still print {System.Collections.Generic.List1[ConsoleApp.Student]} in the debugger, or when converting it to string. I suspect this is why you are confused. You can call .GetType().Name to get the actual typename of an object.

The larger question is, why do you want a IQueryable? This is mostly intended to query databases. If you have objects in memory you usually just use IEnumerable<T>. If you just want to print your students, Overload .ToString on the student object and call string.Join to produce a string for all students.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • I try to do a minimum example. I get data from database using EF and then mapped with `AutoMapper.Map()`. The case is that the mapper returns a `List` and I was requested to apply to this result an IQueryable extension method. Then first I need the data be an IQuerable. – gvd Jan 19 '23 at 16:29
  • No. Since `List` doesn't implement `IQueryable`, `AsQueryable()` can't *cast* it to `IQueryable` but has to *convert* it to `System.Linq.EnumerableQuery` and that's also the type name returned by `ToString()`. There's no wrapping involved. – Gert Arnold Jan 19 '23 at 16:34
  • Maybe the question should be, how to convert a `List` to `IQueryable`? – gvd Jan 19 '23 at 16:59
  • @GertArnold Where did I claim List implements IQueryable? And EnumerableQuery takes the list/enumerable as a constructor parameter and uses this to provide the required interfaces. I would call that a wrapper, but perhaps 'adapter' would be more accurate. I would interpret *convert* to mean to actually copy the elements to some separate internal collection, so the original list object can be released, at least when talking design patterns. – JonasH Jan 20 '23 at 08:02
  • @gvd, `AsQueryable()` does give you an `IQueryable` you can use, nothing more needed. But note that it is somewhat common to have separate extension methods for IQueryable and IEnumerable, since some things may need to be done differently when working with databases. – JonasH Jan 20 '23 at 08:06
  • *Where did I claim...* I didn't say you claimed that, I tried to explain that `.AsQueryable()` either casts or converts. It can only cast if the object already implements `IQueryable`. Therefore, it has to convert here, i.e. create a new object. Of course that doesn't have to be a deep copy. The point is that a new object is created which does *not* return the "wrapped" (whatever "wrapping" may mean) object's name in `ToString()`. You could have noticed that. – Gert Arnold Jan 20 '23 at 09:08
  • "It can only cast if the object already implements `IQueryable`" - that's not true. It has the option to just cast, but it can always still convert to a new type that implements `IQueryable`. – Enigmativity Jan 20 '23 at 09:41
  • 1
    @GertArnold But `EnumerableQuery.ToString()` *does* call `this.enumerable.ToString()` where `enumerable` in this case is the list. At least in .Net 4.8. So the result of `new int[0].AsQueryable().ToString()` *will be* `System.Int32[]`. I'm going to leave the conversion/wrapping debate, since that just seem to be a difference in opinion on nomenclature. – JonasH Jan 20 '23 at 09:44
  • OK, I have to admit (rather sheepishly) that in my test I did `AsQueryable().GetType().ToString()`. That's a major diference. Well, anyway, I hope all this added some clarity on the difference between cast and convert. – Gert Arnold Jan 20 '23 at 09:54
  • As @JonasH I added an `IEnumerable` extension method. – gvd Jan 20 '23 at 10:28