1

2 つのジェネリック型変数が与えられた場合、system.linq.expression ツリーをコンパイルしてそれらを乗算するにはどうすればよいですか? 2 つの型の間に有効な演算子 * がない場合、式が例外をスローしても問題ありません。

System.Linq.Expression を選択したのは、ここでそのように行われたのを見た記憶があるからですが、その方法については十分ではありません。

ありがとう。

編集:スピードのためにLinq式をコンパイルすることを選択しました。これは、合理的に可能な限り高速である必要があります。

4

3 に答える 3

4

次のコードを書くことで、これを行う方法を見つけることができます。

Expression<Func<int, int, int>> multiply = 
    (left, right) => left * right;

アセンブリにコンパイルし、IL逆アセンブラ(Reflectorなど)を使用して、C#コンパイラが生成したコードを確認します。

与えられた例では、C#コンパイラは次のようなものを生成します。

var left = Expression.Parameter(typeof(int), "left");
var right = Expression.Parameter(typeof(int), "right");

var multiply = Expression.Lambda<Func<int, int, int>>(
    Expression.Multiply(left, right),
    new ParameterExpression[] { left, right });

そして、これはまさに乗算式を指定するために必要なことです。

ジェネリックメソッドに配置すると、次のようになります。

public static Func<T, T, T> BuildMultiplier<T>()
{
    var left = Expression.Parameter(typeof(T), "left");
    var right = Expression.Parameter(typeof(T), "right");

    var multiply = Expression.Lambda<Func<T, T, T>>(
        Expression.Multiply(left, right),
        new ParameterExpression[] { left, right });

    return multiply.Compile();
}
于 2012-10-30T20:00:08.700 に答える
2

次のようなものを試してください。

var left = Expression.Parameter(typeof(T), "left");
var right = Expression.Parameter(typeof(T), "right");
var body = Expression.Multiply(left, right);
return Expression.Lambda<Func<T, T, TResult>>(body, left, right);

タイプに有効な乗算演算子がない場合T、そのExpression.Multiply行は例外をスローします。

于 2012-10-30T19:59:57.997 に答える
2

System.Linq.Expression を選択しました

明確にするために:別の簡単な方法があります:

public static T Multiply<T>(T x, T y) {
    return ((dynamic)x) * y;
}

作業 (キャッシュを含む) をフレームワークにオフロードします。もう 1 つのオプション - MiscUtil には、これをまとめた一般的な演算子のサポートがあります -ここからダウンロードできます。

于 2012-10-30T20:06:03.850 に答える