基元类型和Checked、UnChecked操作符的使用

基元类型

 

       编译器直接支持的数据类型成为基元类型。基元类型和.NET框架类库(FCL)中的类型有直接的映射关系。例如在c#中,基元类型int映射到FCL中就是System.Int32。请看下面的四行代码,他们都能通过编译,并且产生的IL代码都是相同的。

            int i = 0;

            System.Int32 i = 0;

            int i = new int();

            System.Int32 i = new System.Int32();

相信的对应关系,大家可以参考MSDN的相关文档。基元类型之间的数据转换可以参考我的上一遍文章,同样存在隐式转换和现实转换,其中的原理都是相同的。当一个值为6.8Single转型为Int32的数据类型时,一些编译器产生的结果可能是7,而另外的编译器产生的结果则可能是6,特别要指出的是,在c#中总是会舍弃小数点后面的数据。

CheckedUnChecked运算符

 

       很多的时候基元类型的数据运算经常导致数据溢出,很多的时候这种情况是非常危险的,甚至产生非常难以查找的Bug。请看下面的代码:

            Byte b = 100;

            b = (Byte)(b + 200);

            Console.WriteLine(b.ToString());

            Console.ReadLine();

输出的结果是大家是意想不到的,44!原因何在?CLR只在32位和64位值上进行算数运算,所以b200都要首先转换成32的数值,然后进行加法运算,这个结果是个32位的数值,然后转换成Byte类型,这种转换,编译器认为是不安全的,所以就要像上面的代码所显示的,要进行显示转换!这种溢出不是我们所期望的,在程序中我们必须检测异常信息,对溢出进行适当的处理。

       C#中的CheckedUnchecked运算符就是处理溢出问题的,并且具有很大的灵活性。我们还是通过下面的代码来分析这个问题。

            try

            {

                Byte b = 100;

                //抛出System.OverflowException异常信息

                b = checked((Byte)(b + 200));

            }

            catch (OverflowException ex)

            {

                //对抛出的异常信息进行处理!

            }

在上面的代码中,checked运算符的检测对象是b+200的运算结果能否转换成Byte类型,很明显,这个结果是溢出的,所以程序在运行时将抛出System.OverflowException异常信息。

            Byte b = 100;

            b = (Byte)checked(b + 200);//不抛出System.OverflowException异常信息

这段代码和上面的代码的不同之处在于,checked运算符的检测对象是不一样的,checked运算符检测的是b+200的结果,很明显,程序不会抛出异常信息。

       C#还提供了checkedUnchecked语句用于对整个语句块中的代码进行溢出检查或者不进行溢出检查!请看下面的代码。

            checked

            {

                Byte b = 100;

                b = (Byte)(b + 200);

            }

由于CheckedUnChecked操作符和语句只影响加,减、乘以及转换IL指令产生的版本,所以在CheckedUnchecked操作符语句内调用一个方法,并不会对该方法内的数据溢出产生影响,这是显而易见的。就像下面的代码一样。原因我在注释中已经写的很清楚了!

            checked

            {

                //假设这个方法的作用是把原来的Byte类型的数加上1000

                //GetSingleMethod()方法是否抛出System.OverflowException

                //异常信息取决与其方法的内部实现,而和现有的checked语句无关!

                GetSingleMethod(1000);

        }

    另外还有一个特例,那就是无论事都是用checkedUnchked关键字,在进行System.Decimal类型的数据运算时,如果发出数据溢出,总是会抛出System.OverflowException异常信息!这是因为CLR没有直接操作System.Decimal类型数据的IL指令!由此可见理解CLR对学习.NET的方方面面都起着至关重要的作用!

 


posted on 2009-03-11 10:10  noviceliu  阅读(362)  评论(0编辑  收藏  举报