Code inspection: IQueryable is possibly unintentionally used as IEnumerable
Category: Potential Code Quality Issues
ID: PossibleUnintendedQueryableAsEnumerable
EditorConfig: resharper_possible_unintended_queryable_as_enumerable_highlighting=[error|warning|suggestion|hint|none]
Language: C#
Requires SWA: No
tip
Objects that implement the IQueryable interface are meant to be processed by LINQ providers (normally, remote databases) with their specific implementations of this interface.
However, as IQueryable
is inherited from IEnumerable, there could be cases when an IQueryable
object is passed and processed as an IEnumerable
object, meaning that all processing is done on the local machine. Such implicit conversions are not a problem in test environments, but could make a huge performance impact in production.
Suppose that you get an IQueryable
object from a database:
IQueryable<Resource> resources = myDb.GetResources();
... and somewhere in your codebase there is a handy extension method for filtering out null items:
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> items)
{
return items.Where(x => x != null);
}
Now, let's see how we can use our queryable object:
// 'Where' will be processed in the database server and we just get the result:
var notNullResources1 = resources.Where(x => x != null);
// We will first get all Resource objects from the database
// and then process them locally.
// Also, 'notNullResources2' will be of the 'IEnumerable' type,
// so all other processing of this object will be done locally as well.
var notNullResources2 = resources.WhereNotNull();
ReSharper will detect such a conversion and suggest a fix to make it explicit:
var notNullResources2 = resources.AsEnumerable().WhereNotNull();
Another example is method groups or expression trees, which should not be passed as 'Expression' objects in this case, and therefore trigger the same inspection. The same implicit conversion to IEnumerable
happens here and ReSharper suggests adding the explicit .AsEnumerable()
to the call:
Suboptimal code
public static Func<object, bool> NotNullCondition => (x) => x != null;public static void Test(IQueryable<object> resources){ if (resources != null) { var notNullResources = resources.Select(NotNullCondition); }}
After the quick-fix
public static Func<object, bool> NotNullCondition => (x) => x != null;public static void Test(IQueryable<object> resources){ if (resources != null) { var notNullResources = resources.AsEnumerable().Select(NotNullCondition); }}