重要問題は、「Queryable.OfType は何をするのか」ではなく、「そこにあるコードはどのようにそれを達成するのか」です。
Queryable.OfType を振り返ると、(いくつかのクリーンアップ後) が表示されます。
public static IQueryable<TResult> OfType<TResult>(this IQueryable source)
{
return (IQueryable<TResult>)source.Provider.CreateQuery(
Expression.Call(
null,
((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(
new Type[] { typeof(TResult) }) ,
new Expression[] { source.Expression }));
}
だから、私がこれをまっすぐに持っているかどうか見てみましょう:
- リフレクションを使用して、現在のメソッド (OfType) への参照を取得します。
- MakeGenericMethod を使用して、現在のメソッドの型パラメーターをまったく同じものに変更することにより、まったく同じ新しいメソッドを作成します。
- その新しいメソッドへの引数は、source ではなく source.Expression になります。これは IQueryable ではありませんが、すべてを Expression.Call に渡すので、問題ありません。
- Expression.Call を呼び出し、
メソッド (変ですか?)インスタンスnullとして渡し、クローン化されたメソッドをその引数として渡します。 - その結果を CreateQuery に渡し、結果をキャストします。これは、全体の中で最も健全な部分のようです。
このメソッドの効果は、型が TResult またはそのサブタイプの 1 つと等しくない値を返すことを省略するようプロバイダーに指示する式を返すことです。しかし、上記の手順が実際にこれをどのように達成するかわかりません。IQueryable<TResult> を返すメソッドを表す式を作成し、そのメソッドの本体を単純にソース式全体にして、型を見ないようにしているようです。IQueryable プロバイダーが、選択されたタイプ以外のレコードを黙って返さないことが単純に期待されるのでしょうか?
上記の手順は何らかの点で間違っていますか、それとも実行時に観察される動作がどのように発生するかわかりませんか?