美文网首页常见编程问题锦集
“System.InvalidCastException 指定的

“System.InvalidCastException 指定的

作者: 炉石不传说 | 来源:发表于2020-06-13 16:17 被阅读0次

一次简单的拆箱操作,竟然出来了异常,导致APP在iOS手机上面闪退了。

对面的异常进行反思和总结如下:

一、装箱和拆箱

装箱:把值类型转成引用类型

拆箱:把引用类型转成值类型

从定义中可以看出装箱和拆箱操作只可能发生在值类型之间的转换,引用类型之间是不会出现装箱和拆箱操作的。

装箱:object obj=1;

上述代码即为一次装箱过程。系统首先会建立一个索引为[0] object类型的局部变量,将整形数1从栈中取出放在栈顶,执行box指令并在托管堆上申请System.Int32所需内存空间。将栈上的变量弹出存储到索引为0的局部变量中。此操作不可避免的要在堆上申请内存空间,并将堆栈上的值类型数据复制到申请的堆内存空间上,这肯定是要消耗内存和cpu资源的。

拆箱:int x=(int)obj;

上述代码即为一次拆箱过程。系统首先会建立一个索引为[1]的int32类型局部变量,将堆上索引为[0]的变量值取出压入栈顶,执行unbox.any指令,生成System.Int32地址指针并读取数据存入栈。后将栈上的变量存储到索引为[1]的int32类型变量中。拆箱操作的执行过程和装箱操作过程正好相反,是将存储在堆上的引用类型值转换为值类型并给值类型变量。

由于装箱操作和拆箱操作是要额外耗费cpu和内存资源的,所以项目开发中尽量使用泛型定义来避免装箱和拆箱的出现。

二、数字类型之间的转换--(int)和int.Parse()和int.TryParse()和Convert.ToInt32()

private void ConvertType()

        {

            ////////////////////////////////////////////////////////////////null type

            int val1 = Convert.ToInt32(null); //0

            //int val2 = int.Parse(null); //Error: System.ArgumentNullException:“值不能为 null。Arg_ParamName_Name”

            int val3; //0

            bool bVal3 = int.TryParse(null, out val3);//false

            //int val4 = (int)null; //Error: 无法将 null 转换为int,因为后者是不可以为null的值类型

            ////////////////////////////////////////////////////////////////number type

            float f = 1.1111f;

            int val5 = Convert.ToInt32(f);//1  //采取的取舍是进行四舍五入

            //int val6 = int.Parse(f.ToString());//Error: System.FormatException:“输入字符串的格式不正确。”

            int val7;//0

            bool bVal7 = int.TryParse(f.ToString(), out val7);//false

            int val8 = (int)f;//1  //截取浮点型的整数部分,忽略小数部分。即向下取整

            long l = 9111111111111111111;

            //int val9 = Convert.ToInt32(l);//Error; System.OverflowException:“值对于 Int32 太大或太小。”

            //int val10 = int.Parse(l.ToString());//Error: System.OverflowException:“值对于 Int32 太大或太小。”

            int val11;//0

            bool bVal11 = int.TryParse(l.ToString(), out val11);//false

            int val12 = (int)l;//1726247367

            ////////////////////////////////////////////////////////////////string type

            string s1 = "";

            //int val13 = Convert.ToInt32(s1);//Error: System.FormatException:“输入字符串的格式不正确。”

            //int val14 = int.Parse(s1);//Error: System.FormatException:“输入字符串的格式不正确。”

            int val15;//0

            bool bVal15 = int.TryParse(s1, out val15);//false

            //int val16 = (int)s1;//Error: 无法将string转换为int

            string s2 = "1.111";

            //int val17 = Convert.ToInt32(s2);//Error: System.FormatException:“输入字符串的格式不正确。”

            //int val18 = int.Parse(s2);//Error: System.FormatException:“输入字符串的格式不正确。”

            int val19;//0

            bool bVal19 = int.TryParse(s2, out val19);//false

            //int val20 = (int)s1;//Error: 无法将string转换为int

            Console.WriteLine("ConvertType Over");

        }

对上面的测试代码进行总结:

1、null 空类型的转换:int.Parse()和直接强转是会报错的,其他转换返回0

2、number 数字类型的转换:Convert.ToInt32()是参与四舍五入取值,强转是直接向下取整。对于大值转向小值,Convert.ToInt32和int.Parse都会报错,

虽然强转不会报错,但是精度不对,会对原数据进行截取,结果也是错误的。

3、string 字符串类型的转换:对于空字符和浮点数的string的转换int,只有int.TryParse不会报错,其他都会报错。策划配置表经常出现类似的配置问题,需要注意。

综上,我们对数据转换要特别谨慎,选择合适的函数,才能保证不会出错。建议如果是数值类型直接的转换直接可以强转。如果是字符串类型的转换建议int.Parse和int.TryParse

如果是装拆箱建议用Convert.ToInt32。实在不知道选择哪个类型建议用int.TryParse,做好对转换返回值bool的判断就可以了

相关文章

网友评论

    本文标题:“System.InvalidCastException 指定的

    本文链接:https://www.haomeiwen.com/subject/czxztktx.html