次のパラメータを取る一般的なメソッドを考えるとGet<T>
...
Expression<Func<T,bool>> foo
そのメソッド本体内で、「T」が typeof(Stuff) であるかどうかをテストし、そうであればキャストします。
Expression<Func<Stuff,bool>> boo = (???) foo;
私が期待する最初の反応は、「キャストする必要はありませんStuff
。渡された場合は、すでに型になっています」というものです。しかし、メソッドのディスパッチに関しては、そうではないことがわかりました!!
はい、テストしてキャストする必要がありますが、方法がわかりません。
以下は、これが必要な理由と場所のコンテキストです。
次のようなコードがあります。
public class Stuff {
public int Alpha;
}
interface ISomething {
List<T> Get<T>(Expression<Func<T,bool>> lambda);
}
public class Something : ISomething {
List<T> Get<T>(Expression<Func<T,bool>> expr){
//...
//Makes non-recursive call to non-generic 'Get' method.
//Works as expected.
Get((Stuff x) => x.Alpha > 10);
//UH-OH! makes recursive call to Get<T> even when T is typeof(Stuff)!
//This is where casting is needed!
Get(expr);
//...
}
List<Stuff> Get(Expression<Func<Stuff,bool>> expr){
//...
}
}
私の意図は、 type のパラメーターを具体的に受け取る場合、ジェネリックメソッドGet<T>
に非ジェネリックを呼び出すようにすることです。しかし、それは上記のコードでは起こりません。 Get
expr
LambdaExpression
Stuff
このコードを実行すると...
ISomething foo = new Something();
var result = foo.Get((Stuff x) => x.Alpha < 20);
...呼び出される関数は ですGet<T>
。ISomething インターフェイス内で使用可能な唯一のGet
一致であるため、非ジェネリックの方がより適切に一致するとしても、これは驚くべきことではありません。Get<T>
だからこれでOKです。
しかし、Get<T>
メソッドが実行されたら、非ジェネリックGet
を という名前の同じ引数で呼び出す必要がありますexpr
。私が観察している動作を考えると、 to をキャストした場合にのみ、必要なものを取得できるように見えExpression<Func<T,bool>>
ますExpression<Func<Stuff,bool>>
。is
これは、またはas
のようなテストを行って、キャスト可能であることを確認することも前提としています。
型テストはどのように行われ、キャストはどのように行われますか?
より具体的で非ジェネリックなGet
メソッドを強制的に呼び出す別の方法はありますか? ISomething
発信者はインターフェイスのみを介して作業する必要があると想定してください。
Get
確かに、非ジェネリックがまったく通過せずにすぐに呼び出された場合は、さらに理想的ですGet<T>
。しかし、ISomething
インターフェースを介して作業することを余儀なくされた場合、それは不可能だと思います.
参考までに、これを機能させる方法が見つかれば、C++の " traits - else-then-if " に似た機能を提供することになります。