本文由 比特飞 原创发布,欢迎大家踊跃转载。
转载请注明本文地址:https://www.byteflying.com/archives/6710。
编写高质量代码的50条黄金守则-Day 03(首选is或as而不是强制类型转换),本文由比特飞原创发布,转载务必在文章开头附带链接:https://www.byteflying.com/archives/6710
该系列文章由比特飞原创发布,计划用半年时间写完全50篇文章,为大家提供编写高质量代码的一般准则。
1、概述
在 .net 中包含三种基本的类型转换,is 操作符转换,as 操作符转换,强制类型转换,这三种类型转换各有不同却又各有联系。使用不当,可能引发 NullPointerException 异常或 InvalidCastException 异常。本文将通过一些演示案例为大家一探究竟。
2、通过反编译查看IL,探究类型转换的本质
接下来,我们先来准备环境:
namespace EffectiveCoding03 { public class Program { public class TypeBase { } public class TypeSub : TypeBase { } public class TypeThree { } public static void Main(string[] args) { TestIs(); TestAs(); TestConvert(); TestUserConvert(); TestIteration(); TestLinq(); } }}
TypeSub 继承自 TypeBase,TypeThree 为另外一种类型。
1、is 关键字转换
再看看 TestIs 方法:
public static void TestIs() { var foo = new TypeSub(); if (foo is TypeSub) { Console.WriteLine("foo is TypeSub => success"); } else { Console.WriteLine("foo is TypeSub => failure"); } if (foo is TypeBase) { Console.WriteLine("foo is TypeBase => success"); } else { Console.WriteLine("foo is TypeBase => failure"); }}
先使用 is 测试变量 foo 的类型,再根据结果输出测试结果,以下是输出结果:
foo is TypeSub => successfoo is TypeBase => success
结果不出意外,均能命中,因为子类的类型能匹配本身类型,也能匹配其父类型。接下来我们看看它们的 IL:
// Token: 0x06000002 RID: 2 RVA: 0x00002070 File Offset: 0x00000270.method public hidebysig staticvoid TestIs () cil managed{ // Header Size: 12 bytes // Code Size: 80 (0x50) bytes // LocalVarSig Token: 0x11000001 RID: 1 .maxstack 2 .locals init ([0] class EffectiveCoding03.Program/TypeSub foo,[1] bool,[2] bool)/* (27,37)-(27,38) C:甥敳獲AdministratorsourceeposEffectiveCoding03EffectiveCoding03Program.cs *//* 0x0000027C 00 */ IL_0000: nop/* (28,13)-(28,37) C:甥敳獲AdministratorsourceeposEffectiveCoding03EffectiveCoding03Program.cs *//* 0x0000027D 7307000006 */ IL_0001: newobj instance void EffectiveCoding03.Program/TypeSub::.ctor()/* 0x00000282 0A */ IL_0006: stloc.0/* (30,13)-(30,32) C:甥敳獲AdministratorsourceeposEffectiveCoding03EffectiveCoding03Program.cs *//* 0x00000283 06 */ IL_0007: ldloc.0/* 0x00000284 14 */ IL_0008: ldnull/* 0x00000285 FE03 */ IL_0009: cgt.un/* 0x00000287 0B */ IL_000B: stloc.1/* (hidden)-(hidden) C:甥敳獲AdministratorsourceeposEffectiveCoding03EffectiveCoding03Program.cs *//* 0x00000288 07 */ IL_000C: ldloc.1/* 0x00000289 2C0F */ IL_000D: brfalse.s IL_001E/* (30,33)-(30,34) C:甥敳獲AdministratorsourceeposEffectiveCoding03EffectiveCoding03Program.cs *//* 0x0000028B 00 */ IL_000F: nop/* (31,17)-(31,64) C:甥敳獲AdministratorsourceeposEffectiveCoding03EffectiveCoding03Program.cs *//* 0x0000028C 721B000070 */ IL_0010: ldstr "foo is TypeSub => success