“System.InvalidCastException 指定的转换无效” 问题的反思和总结

一次简单的拆箱操作,竟然出来了异常,导致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的判断就可以了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容