SEHException .net难题

时间:2011-03-29 15:11:55

标签: c# .net puzzle

任何人都可以解释为什么下面的代码会抛出错误。可以通过将-1值转换为十进制(-1M),通过更改运算符重载以接受int或不使用可空对象来轻松修复它。

我注意到只有VS208才会在VS2010中抛出错误。

class Program
{
    static void Main(string[] args)
    {
        var o1 = new MyObject?(new MyObject(2.34M));
        o1 *= -1;
    }
}

public struct MyObject
{
    public MyObject(Decimal myValue)
    {
        this.myValue = myValue;
    }

    private Decimal myValue;

    public static MyObject operator *(MyObject value1, decimal value2)
    {
        value1.myValue *= value2;
        return value1;
    }
}

3 个答案:

答案 0 :(得分:1)

在VS 2008和VS 2010中都可以正常工作(在我的计算机上)。顺便说一下,*的实现不正确。它应该是:

public static MyObject operator *(MyObject value1, int value2)
{
    return new MyObject(value1.myValue * value2);
}

可能你的意思是operator *(MyObject value1, decimal value2)真的失败了。

答案 1 :(得分:1)

没有给定代码段的repro。但是,您使用的代码非常类似于C#编译器中的旧错误所涉及的代码类型。细节在this thread,Eric Lippert已经知道了。

答案 2 :(得分:1)

只是为此添加一些内容,下面的代码重新排序操作数,不再抛出异常,而是当程序退出时,myValue的值是(正确)'无效的十进制值'。

请注意,只有操作数的顺序发生了变化,我们将main中的* =扩展为更明确并支持此操作。

我不会期望这些外观变化可以防止抛出异常..但是他们确实如此。

认为这可能与以不同顺序推送到堆栈的值有关?

// If you invert the order of the operands to MyObject.*() , and expand out the *= in main,
// the thing runs without throwing the exception :s

// If you step through, the value of myValue is correctly ‘invalid decimal value’ after * by -1.

using System;

namespace ConsoleApplication19
{
    class Program
    {
        static void Main(string[] args)
        {
            var o1 = (MyObject?)new MyObject(2.34M);
            o1 = -1 * o1 ;
        }
    }

    public struct MyObject
    {
        private Decimal myValue;

        public MyObject(Decimal myValue)
        {
            this.myValue = myValue;
        }

        public static MyObject operator *(Decimal value2,  MyObject value1)
        {
            value1.myValue *= value2;
            return value1;
        }
    }
}