2

次のパラメータを取る一般的なメソッドを考えると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>に非ジェネリックを呼び出すようにすることです。しかし、それは上記のコードでは起こりません。 Getexpr LambdaExpressionStuff

このコードを実行すると...

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 " に似た機能を提供することになります。

4

1 に答える 1

3

このようなものはどうですか:

public List<T> Get<T>(Expression<Func<T,bool>> expr){
    var expr2 = expr as Expression<Func<Stuff, bool>>;
    if (expr2 != null){
        return Get(expr2) as List<T>;
    }

    //...
}

このコードはReSharperをびっくりさせますが、うまくいくようです:)

可能であれば、非ジェネリック オーバーロードを ISomething に追加することをお勧めします。

于 2013-03-12T04:51:04.977 に答える