2

多くの異なるタイプの入力を処理できるクラスを作成しようとしていますが、それらはすべて同じインターフェースを実装しています。

次のコードがあります。

private IEnumerable<IPlan> DevisePlans(ITile tile, IEnumerable<ISpace> spaces)
{
    MethodInfo method = GetType().GetMethod("DevisePlans",
                                            BindingFlags.NonPublic | BindingFlags.Instance,
                                            null,
                                            new[] {tile.GetType(), typeof(ISpace)},
                                            null);
    var type = typeof(Func<,,>).MakeGenericType(tile.GetType(), typeof(ISpace), typeof(IEnumerable<IPlan>));
    var planner = Delegate.CreateDelegate(type, this, method);
    return spaces.SelectMany(s => (IEnumerable<IPlan>)planner.DynamicInvoke(tile, s));
}

DevisePlansクラス内には のさまざまな実装が多数あり、それぞれに を実装する最初のパラメータ タイプがありますITile

private IEnumerable<IPlan> DevisePlans(Foo tile, ISpace space) { /* ... */ }
private IEnumerable<IPlan> DevisePlans(Bar tile, ISpace space) { /* ... */ }

DynamicInvokeこれは機能しますが、列挙可能なすべての反復を呼び出しています。動的呼び出しを完全に回避できない場合でも、動的呼び出しがループ内に存在しないようにこのメソッドを最適化する方法はありますか?

4

3 に答える 3

5

これを使用して、提供されたの最も具体的なオーバーロード (オーバーライドではない) を呼び出しているようです。私の理解が正しいと仮定すると(私が間違っている場合は教えてください)、そのまま使用してください-組み込みのキャッシュがあり、これに最適化されています:DevisePlanstiledynamic

return spaces.SelectMany(s =>
    (IEnumerable<IPlan>)DevisePlans((dynamic)tile, (dynamic)s)
);

そして...それだけです!

ITileただし、ポリモーフィズム ( に対して) または C# 4.0 の分散のいずれかを含む答えを探したくなるでしょう。

于 2012-04-25T20:28:16.407 に答える
0

式ツリー (Expression.Call から開始) を作成してコンパイルすると、高速なデリゲートが作成されます。同じ型に対して複数回コンパイルしないように、型に基づいてデリゲートをキャッシュする必要があります。

于 2012-04-25T20:24:13.993 に答える
0

ここで探しているのはビジター パターンだと思います。各タイプのオーバーロードを使用して ITileVisitor インターフェイスを定義すると、ITile には、ビジターをパラメーターとして受け取る Visit メソッドがあります。正しい Devise オーバーロードが呼び出されるようにする Visit の実装です。

于 2012-04-25T20:59:31.923 に答える