You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#编译器如何区分Where方法的Func与Expression两种重载?

How the C# Compiler Chooses the Right Where Method for IQueryable<T>

Great question! Let's walk through exactly how the compiler decides which Where overload to use in your code.

First, let's recap the context you provided:

  • list.AsQueryable() returns an instance of IQueryable<int>
  • IQueryable<int> inherits from IEnumerable<int>, and declares its own Where(Expression<Func<int, bool>>) method
  • IEnumerable<int> defines the Where(Func<int, bool>) method

Here's the step-by-step breakdown of the compiler's decision process:

1. Collect all candidate Where methods

When you call .Where(x => x > 0) on an IQueryable<int> instance, the compiler first gathers every available method named Where that could apply. This includes:

  • The Where(Expression<Func<int, bool>>) method directly declared on IQueryable<int>
  • The Where(Func<int, bool>) method inherited from IEnumerable<int>

2. Filter for "feasible" methods

Next, the compiler checks which of these methods can actually accept your argument (x => x > 0). A lambda expression like this can be implicitly converted to two different types:

  • Func<int, bool>: A delegate that represents executable code
  • Expression<Func<int, bool>>: An expression tree that represents the structure of the code (not the code itself)

Since both conversions are valid, both Where methods are considered feasible candidates.

3. Select the best match

This is where the compiler's overload resolution rules kick in. The key factors here are:

  • Prefer methods declared directly on the target type: The Where(Expression<...>) method is part of IQueryable<int> itself, while the other is inherited from a base interface. The compiler prioritizes methods defined directly on the type you're calling against.
  • Align with the type's design intent: IQueryable<T> is built to work with expression trees (so queries can be translated to SQL, LINQ to Entities, etc.). The compiler recognizes this design goal and leans toward the overload that fits the type's purpose.

Proof of this behavior

You can force the compiler to pick the other overload by explicitly converting the lambda to the desired type:

// Forces the use of IEnumerable<int>.Where(Func<int, bool>)
var positives = list.AsQueryable().Where((Func<int, bool>)(x => x > 0));

// Forces the use of IQueryable<int>.Where(Expression<Func<int, bool>>)
var positives = list.AsQueryable().Where((Expression<Func<int, bool>>)(x => x > 0));

内容的提问来源于stack exchange,提问作者Spiff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:59:56