I came across this post while I was looking for things to improve performance. Currently, in my application we are returning IList<>
all over the place. Is it a good idea to change all of these returns to AsQueryable()
?
Here is what I found -
AsQueryable()
- Context needs to be
open and you cannot control the
lifetime of the database context
it need to be disposed properly. Also
it is deferred execution('faster
filtering' as compared to Lists)IList<>
- This should be preferred
over List<>
as it provides a barebone
and lightweight implementation.Also when should be one preferred over another ? I know the basics but I am sorry I am still not clear when and how should we use them correctly in an application. It would be great to know this as the next time I would try to keep it in mind before returning anything..Thanks a lot.
Basically, you should try to reference the widest type you need. For example, if some variable is declared as List<...>
, you put a constraint for the type of the values that can be assigned to it. It may happen that you need only sequential access, so it would be enough to declare the variable as IEnumerable<...>
instead. That will allow you to assign the values of other types to the variable, as well as the results of LINQ operations.
If you see that your variable needs access by index, you can again declare it as IList<...>
and not just List<...>
, allowing other types implementing IList<...>
be assigned to it.
For the function return types, it depends upon you. If you think it's important that the function returns exactly List<...>
, you declare it to return exactly List<...>
. If the only important thing is access to the result by index, perhaps you don't need to constrain yourself to return exactly List<...>
, you may declare return type as IList<...>
(but return actually an instance of List<...>
in this implementation, and possibly of some another type supporting IList<...>
later). Again, if you see that the only important thing about the return value of your function is that it can be enumerated (and the access by index is not needed), you should change the function return type to IEnumerable<...>
, giving yourself more freedom.
Now, about AsQueriable
, again it depends on your logic. If you think that possible delayed evaluation is a good thing in your case, as it may aid to avoid the unneeded calculations, or you intend to use it as a part of some another query, you use it. If you think that the results have to be "materialized", i.e., calculated at this very moment, you would better return a List<...>
. You would especially need to materialize your result if the calculation later may result in a different list!
With the database a good rule of thumb is to use AsQueriable
for the short-term intermediate results, but List
for the "final" results which will be used within some longer time. Of course having a non-materialized query hanging around makes closing the database impossible (since at the moment of actual evaluation of the the database should be still open).