Вопрос

Дано два шорта (System.Int16)

short left = short.MaxValue;
short right = 1;

Я хочу получить OverflowException при их добавлении.

checked(left+right)

не работает, потому что в результате left+right является Int32.

checked((short)(left+right))

работает, как и ожидалось.

Моя проблема в том, что при использовании деревьев выражений "трюк" не работает:

var a = Expression.Constant(left);
var b = Expression.Constant(right);
var sum = Expression.ConvertChecked(Expression.Add(a, b), typeof(short));
var l = Expression.Lambda(sum);
var f = (Func<short>)l.Compile();

Зовущий f() не создает исключение переполнения, но возвращает -32768.Что случилось?

Это было полезно?

Решение

Проблема в том, что добавление является выполняется как short + short (который предположительно существует в IL, даже если он не существует в C #) - и затем преобразование выполняется отдельно.Это показано этой полной программой - даже без преобразования результат равен -32768:

using System;
using System.Linq.Expressions;

class Test
{
    static void Main(string[] args)
    {
        short left = short.MaxValue;
        short right = 1;
        var a = Expression.Constant(left);
        var b = Expression.Constant(right);
        var sum = Expression.Add(a, b);
        var convert = Expression.ConvertChecked(sum, typeof(short));
        var convertLambda = Expression.Lambda<Func<short>>(convert);
        var convertFunc = convertLambda.Compile();
        Console.WriteLine("Conversion: {0}", convertFunc());
        var sumLambda = Expression.Lambda<Func<short>>(sum);
        var sumFunc = sumLambda.Compile();
        Console.WriteLine("Sum: {0}", sumFunc());
    }
}

Если вы заставите его выполнить сложение int + int, а затем преобразование, это вызовет исключение переполнения:

using System;
using System.Linq.Expressions;

class Test
{
    static void Main(string[] args)
    {
        short left = short.MaxValue;
        short right = 1;
        var a = Expression.Constant((int) left);
        var b = Expression.Constant((int) right);
        var sum = Expression.Add(a, b);
        var convert = Expression.ConvertChecked(sum, typeof(short));
        var convertLambda = Expression.Lambda<Func<short>>(convert);
        var convertFunc = convertLambda.Compile();
        Console.WriteLine("Conversion: {0}", convertFunc());
        var sumLambda = Expression.Lambda<Func<int>>(sum);
        var sumFunc = sumLambda.Compile();
        Console.WriteLine("Sum: {0}", sumFunc());
    }
}

Я не знаю почему AddChecked однако это не работает...это похоже на ошибку: ( Возможно, что использование перегрузка, которая позволяет указать Метод, будет работать, но я не уверен...

Другие советы

Спасибо.

Другими словами:То, что вы видите в C #, не может быть переведено 1: 1 в Деревья выражений.Интересно почему они решили неявно увеличить сумму двух коротких значений до int.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top