2011-07-30 12 views
9

Dlaczego następujący kod zgłasza wyjątek w środowisku wykonawczym, a robi to w tradycyjny sposób kompiluje bez problemu?Operator binarny Multiply nie jest zdefiniowany dla typów "System.Int32" i "System.Double".

var left = Expression.Constant(25d); 
var right = Expression.Constant(20); 

// Throws an InvalidOperationException! 
var multiplyExpression = Expression.Multiply(left, right); 

var multiply = 25d * 20; 
Debug.WriteLine(multiply.ToString()); // Works normally! 

nie użyje Expression.Convert ponieważ nie mogę dokładnie określić, których ekspresja powinny zostać przekształcone.

+4

Ponieważ w tradycyjny sposób, kompilator wstawia (moralny odpowiednik) 'Expression.Convert' - używając reguł pierwszeństwa typu, aby określić stronę do konwersji. –

+0

Które wyrażenie kompilator C# został w tym przypadku przekonwertowany? –

+1

Po prostu sprawdź typ "rozmnażaj", który powie Ci, która strona wymaga konwersji. – MerickOWA

Odpowiedz

7

Cóż, odkryłem, jak rozwiązać problem, używając wyliczenia TypeCode, aby określić, który węzeł miałby wyższą precyzję, a następnie przekonwertować typ drugiego węzła na typ poprzedniego i na odwrót:

private static void Visit(ref Expression left, ref Expression right) 
    { 
    var leftTypeCode = Type.GetTypeCode(left.Type); 
    var rightTypeCode = Type.GetTypeCode(right.Type); 

    if (leftTypeCode == rightTypeCode) 
     return; 

    if (leftTypeCode > rightTypeCode) 
     right = Expression.Convert(right, left.Type); 
    else 
     left = Expression.Convert(left, right.Type); 
    } 
+0

Oh tama ... TypeCode nie jest dostępny w sklepie Windows. tak blisko... ;( –

0

Cóż, komunikat o błędzie w tytule informuje Cię, dlaczego istnieje wyjątek.

Nie ma zdefiniowanej metody Expression.Multiply, która przyjmuje argumenty w postaci System.Int32 i System.Double.

Urządzenie * będzie działać, ponieważ ma niższy poziom, a Twoje wartości będą automatycznie przesyłane.

0
var left = Expression.Constant(25d); 
var right = Expression.Constant((double)20); 

var multiplyExpression = Expression.Multiply(left, right); // works 
+0

Nie można tego zrobić bezpośrednio, powinienem nazwać Expression.Convert w jakiś sposób. –

7
var left = Expression.Constant(25d); 
var right = Expression.Constant(20); 
var multiplyExpression = Expression.Multiply(
    left, 
    Expression.Convert(right, left.Type)); 

Lub, jeśli nie wiesz, że lewa strona ma wyższą precyzję i chcesz zawsze skończyć z double rezultacie można powiedzieć coś takiego:

Expression left = Expression.Constant(2); 
Expression right = Expression.Constant(25.1); 
left = Expression.Convert(left, typeof(double)); 
right = Expression.Convert(right, typeof(double)); 
var multiplyExpression = Expression.Multiply(left, right); 
+0

Cóż, to wygląda dobrze, ale jak to zrobić, jeśli operandy są typu float, dziesiętny? –

+1

@Islam Ibrahim: Istnieje wiele możliwości i zazwyczaj najlepiej jest wybrać najprostszą strategię, która zadziała w twoim przypadku. Być może, jeśli udostępnisz więcej informacji na temat swoich wymagań i do czego jest to używane, możemy pomóc Ci znaleźć rozwiązanie, które będzie pasowało. Na przykład, czy wiesz, jaki typ chcesz zakończyć z wyprzedzeniem, czy też zmieni się on w zależności od danych wejściowych? – StriplingWarrior

Powiązane problemy