4

MiscUtil Operators をしばらく使用していますが、大きな問題はありません。しかし今、私は本当に私を悩ませているものを見つけました:

byte first = 13;
byte second = 29;

byte result = MiscUtil.Operator.Add(first, second);

この方程式の単純な期待される結果は次のようになるはずですresult == 42が、残念ながらこれは次の結果をスローしInvalidOperationExceptionます。

The binary operator Add is not defined for the types 'System.Byte' and 'System.Byte'.

この奇妙な動作を詳しく見てみると、System.Byte実際にはこれらの演算子が実装されていないことがわかります。C# 内では、これらの型は暗黙的にInt32and に変換され、これらの演算子を実装します。

そこで問題は、MiscUtil をbyteandで動作させる機会はありsbyteますか?

4

2 に答える 2

5

技術的には、intなどこれらの演算子を実装していません。これらは、通常の意味での「演算子」(static-を含む)によって提供されるのではなく、オペコードcallによって直接表されます。add最終的に、この場合の失敗は実際にはExpressionAPIに起因します。

var x = Expression.Parameter(typeof(byte));
var y = Expression.Parameter(typeof(byte));
var func = Expression.Lambda<Func<byte,byte,byte>>(
    Expression.Add(x,y), x, y).Compile(); // explodes here

これを修正するには、MiscUtilはbyte/sbyteバージョンを特殊なケースにする必要があります。何かのようなもの:

var x = Expression.Parameter(typeof(byte));
var y = Expression.Parameter(typeof(byte));
var func = Expression.Lambda<Func<byte,byte,byte>>(
    Expression.Convert(
        Expression.Add(
            Expression.Convert(x, typeof(int)),
            Expression.Convert(y, typeof(int))
         ),typeof(byte)), x, y).Compile();

でも!ジョンのレポの鍵を知ってから久しぶりです;p

奇妙なことに、生のILですべてを実装するのはそれほど難しいことではありません...私は実際に(USBドライブ上で)非常に古い.NET 2.0(つまり以前Expressionの)バージョンの「汎用演算子」に遭遇しました私が何年も前に書いたもので、それでうまくいくかもしれません。または簡単:MiscUtilにローカルでパッチを適用してbyte/を処理しsbyteます。

于 2013-01-16T13:12:12.437 に答える
2

Marc の回答のおかげで、ローカル バージョンの MiscUtil にパッチを適用しました。ExpressionUtil.csファイルを使用して、次のパッチを適用しました。

Index: ExpressionUtil.cs
===================================================================
--- ExpressionUtil.cs
+++ ExpressionUtil.cs
@@ -68,6 +68,18 @@
             {
                 try
                 {
+                    if (typeof(TArg1) == typeof(byte)
+                       || typeof(TArg1) == typeof(sbyte)
+                       || typeof(TArg2) == typeof(byte)
+                       || typeof(TArg2) == typeof(sbyte))
+                    {
+                        return Expression.Lambda<Func<TArg1, TArg2, TResult>>(
+                            Expression.Convert(body(
+                                    Expression.Convert(lhs, typeof(int)),
+                                    Expression.Convert(rhs, typeof(int))
+                                 ), typeof(TResult)), lhs, rhs).Compile();
+                    }
+
                     return Expression.Lambda<Func<TArg1, TArg2, TResult>>(body(lhs, rhs), lhs, rhs).Compile();
                 }
                 catch (InvalidOperationException)

そのため、ある晴れた日に公式バージョンが更新されるか、必要な人はここから取得してローカルにパッチを適用できます.

于 2013-01-16T14:13:22.877 に答える