Given two shorts (System.Int16
)
short left = short.MaxValue;
short right = 1;
I want to get an OverflowException
when adding them.
checked(left+right)
does not work, because the result of left+right
is an Int32
.
checked((short)(left+right))
works as expected.
My problem is that, using Expression Trees, the "trick" doesn't work:
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();
Calling f()
does not throw an overflow exception but returns -32768
. What's wrong?
The problem is that the addition is being done as short + short (which presumably exists in IL even if it doesn't exist in C#) - and then the conversion is performed separately. This is shown by this complete program - even without the conversion, the result is -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());
}
}
If you make it do an int + int addition and then the conversion, it will throw an overflow exception:
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());
}
}
I don't know why AddChecked
doesn't work though... that looks like a bug :( It's possible that using the overload which allows the Method to specified would work, but I'm not sure...