コードインスペクション:「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);
}
}
2026 年 6 月 12 日