سؤال

إعطاء اثنين من السراويل (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. وبعد ماذا دهاك؟

هل كانت مفيدة؟

المحلول

المشكلة هي أن الإضافة يكون يجري القيام به باعتبارها قصيرة + قصيرة (والتي من المفترض أن تكون موجودة في 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