タイプの変数がある場合、名前空間内で利用可能なIQueryable<T>
4 つの拡張メソッドがあります。Where
Systm.Linq
public static IQueryable<T> Where<T>(this IQueryable<T> source,
Expression<Func<T, bool>> predicate);
public static IQueryable<T> Where<T>(this IQueryable<T> source,
Expression<Func<T, int, bool>> predicate);
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, bool> predicate);
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, int, bool> predicate);
(最後の 2 つは からIQueryable<T>
継承するためIEnumerable<T>
です。)
ObjectQuery<T>
( namespaceで)型の変数を使用する場合、利用可能なSystem.Data.Objects
5 つのオーバーロードがWhere
あります。つまり、上記の 4 つ (ObjectQuery<T>
実装IQueryable<T>
およびIEnumerable<T>
他のインターフェイスの中で) に加えて、このクラスのインスタンス メソッドがあります。
public ObjectQuery<T> Where(string predicate,
params ObjectParameter[] parameters);
IQueryable<T>
どちらかを使用しているときに同じプログラミングの間違いを犯した場合、またはObjectQuery<T>
非常に異なるコンパイラ エラーが発生します。サンプル プログラムを次に示します (VS2010 SP1 の標準 C# コンソール アプリケーション テンプレート +System.Data.Entity.dll
プロジェクト参照に追加されたアセンブリ、4 つの例の下のコメントにコンパイラ エラーがあります)。
using System.Data.Objects;
using System.Linq;
namespace OverloadTest
{
public class Test
{
public int Id { get; set; }
}
class Program
{
static void Main(string[] args)
{
IQueryable<Test> queryable = null;
ObjectQuery<Test> objectQuery = null;
var query1 = queryable.Where(t => t.Name == "XYZ");
// no definition for "Name" in class OverloadTest.Test
var query2 = queryable.Where(t => bla == blabla);
// "bla", "blabla" do not exist in current context
var query3 = objectQuery.Where(t => t.Name == "XYZ");
// Delegate System.Func<Overload.Test,int,bool>
// does not take 1 argument
var query4 = objectQuery.Where(t => bla == blabla);
// Delegate System.Func<Overload.Test,int,bool>
// does not take 1 argument
}
}
}
コンパイラでは、「波線」も異なって見えます。
最初の 2 つのエラーは理解しています。しかし、なぜコンパイラはFunc<T, int, bool> predicate
、最後の 2 つの例でオーバーロード番号 4 (を使用) を使用したいのか、「Name」がクラスTest
で定義されておらず、「bla」と「blabla」が存在しないことを教えてくれないのはなぜですか。現在の文脈では?
私は、コンパイラがオーバーロード番号 5 (as パラメーターを渡さない) とオーバーロード番号 2 と 4 ( 2 つのパラメーターstring
を持つラムダ式を渡さない) を安全に除外できると予想していましたが、私の期待はそうではありません。正しいようです。(t,i) => ...
補足として、この質問を見たときにこの問題に遭遇しました。質問者は、質問の 4 番目のクエリがコンパイルされない (上記の例 3 と 4 のコンパイラ エラーとまったく同じ) と言いましたが、このクエリはまさに彼の問題の解決策であり、私には何か (変数またはプロパティ名?) がクエリに間違って記述されています (ただし、彼はこれを確認していません) が、このコンパイラ エラーは、何が間違っているかを示すのに役立ちません。
編集
以下のMartin Harrisの非常に役立つコメントを参照してください。
例query4
では、「Delegate System.Func does not take 1 argument」というエラーは、波線の上にカーソルを置いたときにツールヒント ウィンドウに表示されるエラーです。コンパイラの出力ウィンドウには、実際には次の順序で 4 つのエラーが表示されます。
- デリゲート System.Func は引数を 1 つ取りません
- 「文字列」はデリゲート型ではないため、「ラムダ式」を「文字列」に変換できません
- 名前「bla」は現在のコンテキストには存在しません
- 名前「blabla」は現在のコンテキストには存在しません
しかし、コンパイラが を使用する最初の 2 つの例で最初のエラーを出さないのはなぜIQueryable<T>
でしょうか?