代码检查:IQueryable 可能被无意中用作 IEnumerable
实现 IQueryable接口的对象旨在由 LINQ 提供程序(通常是远程数据库)通过其特定实现来处理。
然而,由于 IQueryable 继承自 IEnumerable ,可能会出现将 IQueryable 对象作为 IEnumerable 对象传递和处理的情况,这意味着所有处理都在本地计算机上完成。 这种隐式转换在测试环境中不是问题,但在生产环境中可能会对性能产生巨大影响。
假设您从数据库中获取了一个 IQueryable 对象:
IQueryable<Resource> resources = myDb.GetResources();
...并且在您的代码库中某处有一个用于过滤掉空项的便捷扩展方法:
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> items)
{
return items.Where(x => x != null);
}
现在,让我们看看如何使用我们的可查询对象:
// '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 将检测到这种转换并建议进行显式修复:
var notNullResources2 = resources.AsEnumerable().WhereNotNull();
另一个示例是方法组或表达式树,在这种情况下不应作为 'Expression' 对象传递,因此会触发相同的检查。 这里也发生了相同的隐式转换为 IEnumerable ,ReSharper 建议在调用中添加显式 .AsEnumerable()。
public static Func<object, bool> NotNullCondition => (x) => x != null;
public static void Test(IQueryable<object> resources)
{
if (resources != null)
{
var notNullResources =
resources.Select(NotNullCondition);
}
}
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);
}
}
最后修改日期: 2025年 9月 27日