本文由比特飛原創(chuàng)發(fā)布,歡迎大家踴躍轉(zhuǎn)載。
轉(zhuǎn)載請(qǐng)注明本文地址:https://www.byteflying.com/archives/6710。
編寫高質(zhì)量代碼的50條黃金守則-Day 03(首選is或as而不是強(qiáng)制類型轉(zhuǎn)換),本文由比特飛原創(chuàng)發(fā)布,轉(zhuǎn)載務(wù)必在文章開頭附帶鏈接:https://www.byteflying.com/archives/6710
該系列文章由比特飛原創(chuàng)發(fā)布,計(jì)劃用半年時(shí)間寫完全50篇文章,為大家提供編寫高質(zhì)量代碼的一般準(zhǔn)則。
1、概述
在 .net 中包含三種基本的類型轉(zhuǎn)換,is 操作符轉(zhuǎn)換,as 操作符轉(zhuǎn)換,強(qiáng)制類型轉(zhuǎn)換,這三種類型轉(zhuǎn)換各有不同卻又各有聯(lián)系。使用不當(dāng),可能引發(fā) NullPointerException 異?;?InvalidCastException 異常。本文將通過一些演示案例為大家一探究竟。
2、通過反編譯查看IL,探究類型轉(zhuǎn)換的本質(zhì)
接下來,我們先來準(zhǔn)備環(huán)境:
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 關(guān)鍵字轉(zhuǎn)換
再看看 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 測(cè)試變量 foo 的類型,再根據(jù)結(jié)果輸出測(cè)試結(jié)果,以下是輸出結(jié)果:
foo is TypeSub => success
foo is TypeBase => success
結(jié)果不出意外,均能命中,因?yàn)樽宇惖念愋湍芷ヅ浔旧眍愋停材芷ヅ淦涓割愋?。接下來我們看看它們?IL:
// Token: 0x06000002 RID: 2 RVA: 0x00002070 File Offset: 0x00000270
.method public hidebysig static
? ? void 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:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000027C 00? ? ? ? ? */ IL_0000: nop
? ? /* (28,13)-(28,37) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000027D 7307000006? */ IL_0001: newobj? ? instance void EffectiveCoding03.Program/TypeSub::.ctor()
? ? /* 0x00000282 0A? ? ? ? ? */ IL_0006: stloc.0
? ? /* (30,13)-(30,32) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.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:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000288 07? ? ? ? ? */ IL_000C: ldloc.1
? ? /* 0x00000289 2C0F? ? ? ? */ IL_000D: brfalse.s IL_001E
? ? /* (30,33)-(30,34) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000028B 00? ? ? ? ? */ IL_000F: nop
? ? /* (31,17)-(31,64) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000028C 721B000070? */ IL_0010: ldstr? ? "foo is TypeSub => success"
? ? /* 0x00000291 280B00000A? */ IL_0015: call? ? ? void [System.Console]System.Console::WriteLine(string)
? ? /* 0x00000296 00? ? ? ? ? */ IL_001A: nop
? ? /* (32,13)-(32,14) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000297 00? ? ? ? ? */ IL_001B: nop
? ? /* (hidden)-(hidden) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000298 2B0D? ? ? ? */ IL_001C: br.s? ? ? IL_002B
? ? /* (33,18)-(33,19) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000029A 00? ? ? ? ? */ IL_001E: nop
? ? /* (34,17)-(34,64) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000029B 724F000070? */ IL_001F: ldstr? ? "foo is TypeSub => failure"
? ? /* 0x000002A0 280B00000A? */ IL_0024: call? ? ? void [System.Console]System.Console::WriteLine(string)
? ? /* 0x000002A5 00? ? ? ? ? */ IL_0029: nop
? ? /* (35,13)-(35,14) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002A6 00? ? ? ? ? */ IL_002A: nop
? ? /* (37,13)-(37,33) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002A7 06? ? ? ? ? */ IL_002B: ldloc.0
? ? /* 0x000002A8 14? ? ? ? ? */ IL_002C: ldnull
? ? /* 0x000002A9 FE03? ? ? ? */ IL_002D: cgt.un
? ? /* 0x000002AB 0C? ? ? ? ? */ IL_002F: stloc.2
? ? /* (hidden)-(hidden) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002AC 08? ? ? ? ? */ IL_0030: ldloc.2
? ? /* 0x000002AD 2C0F? ? ? ? */ IL_0031: brfalse.s IL_0042
? ? /* (37,34)-(37,35) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002AF 00? ? ? ? ? */ IL_0033: nop
? ? /* (38,17)-(38,65) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002B0 7283000070? */ IL_0034: ldstr? ? "foo is TypeBase => success"
? ? /* 0x000002B5 280B00000A? */ IL_0039: call? ? ? void [System.Console]System.Console::WriteLine(string)
? ? /* 0x000002BA 00? ? ? ? ? */ IL_003E: nop
? ? /* (39,13)-(39,14) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002BB 00? ? ? ? ? */ IL_003F: nop
? ? /* (hidden)-(hidden) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002BC 2B0D? ? ? ? */ IL_0040: br.s? ? ? IL_004F
? ? /* (40,18)-(40,19) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002BE 00? ? ? ? ? */ IL_0042: nop
? ? /* (41,17)-(41,65) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002BF 72B9000070? */ IL_0043: ldstr? ? "foo is TypeBase => failure"
? ? /* 0x000002C4 280B00000A? */ IL_0048: call? ? ? void [System.Console]System.Console::WriteLine(string)
? ? /* 0x000002C9 00? ? ? ? ? */ IL_004D: nop
? ? /* (42,13)-(42,14) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002CA 00? ? ? ? ? */ IL_004E: nop
? ? /* (43,9)-(43,10) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002CB 2A? ? ? ? ? */ IL_004F: ret
} // end of method Program::TestIs
IL 的代碼有些疑惑,我們利用 dnSpy 反編譯看看結(jié)果:
// EffectiveCoding03.Program
// Token: 0x06000002 RID: 2 RVA: 0x00002070 File Offset: 0x00000270
public static void TestIs()
{
? ? Program.TypeSub foo = new Program.TypeSub();
? ? bool flag = foo != null;
? ? if (flag)
? ? {
? ? ? ? Console.WriteLine("foo is TypeSub => success");
? ? }
? ? else
? ? {
? ? ? ? Console.WriteLine("foo is TypeSub => failure");
? ? }
? ? bool flag2 = foo != null;
? ? if (flag2)
? ? {
? ? ? ? Console.WriteLine("foo is TypeBase => success");
? ? }
? ? else
? ? {
? ? ? ? Console.WriteLine("foo is TypeBase => failure");
? ? }
}
結(jié)果是否令你大吃一驚,反編譯結(jié)果顯示foo is TypeSub被編譯器轉(zhuǎn)換為bool flag = foo != null;,這有力的向我們證明了 is 其實(shí)為語法糖,在編譯期間已經(jīng)被寫進(jìn) IL中。
2、as 關(guān)鍵字轉(zhuǎn)換
使用相同的方式測(cè)試 TestAs 方法,我們完全得到一致的結(jié)論。
public static void TestAs() {
? ? var foo = new TypeSub();
? ? //var foo2 = foo as TypeThree; //編譯時(shí)錯(cuò)誤
? ? var foo3 = foo as TypeBase;
? ? if (foo3 != null) {
? ? ? ? Console.WriteLine("foo3 as TypeBase => success");
? ? }
? ? else {
? ? ? ? Console.WriteLine("foo3 as TypeBase => failure");
? ? }
}
// Token: 0x06000003 RID: 3 RVA: 0x000020CC File Offset: 0x000002CC
.method public hidebysig static
? ? void TestAs () cil managed
{
? ? // Header Size: 12 bytes
? ? // Code Size: 46 (0x2E) bytes
? ? // LocalVarSig Token: 0x11000002 RID: 2
? ? .maxstack 2
? ? .locals init (
? ? ? ? [0] class EffectiveCoding03.Program/TypeSub foo,
? ? ? ? [1] class EffectiveCoding03.Program/TypeBase foo3,
? ? ? ? [2] bool
? ? )
? ? /* (45,37)-(45,38) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002D8 00? ? ? ? ? */ IL_0000: nop
? ? /* (46,13)-(46,37) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002D9 7307000006? */ IL_0001: newobj? ? instance void EffectiveCoding03.Program/TypeSub::.ctor()
? ? /* 0x000002DE 0A? ? ? ? ? */ IL_0006: stloc.0
? ? /* (50,13)-(50,40) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002DF 06? ? ? ? ? */ IL_0007: ldloc.0
? ? /* 0x000002E0 0B? ? ? ? ? */ IL_0008: stloc.1
? ? /* (52,13)-(52,30) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002E1 07? ? ? ? ? */ IL_0009: ldloc.1
? ? /* 0x000002E2 14? ? ? ? ? */ IL_000A: ldnull
? ? /* 0x000002E3 FE03? ? ? ? */ IL_000B: cgt.un
? ? /* 0x000002E5 0C? ? ? ? ? */ IL_000D: stloc.2
? ? /* (hidden)-(hidden) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002E6 08? ? ? ? ? */ IL_000E: ldloc.2
? ? /* 0x000002E7 2C0F? ? ? ? */ IL_000F: brfalse.s IL_0020
? ? /* (52,31)-(52,32) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002E9 00? ? ? ? ? */ IL_0011: nop
? ? /* (53,17)-(53,66) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002EA 72EF000070? */ IL_0012: ldstr? ? "foo3 as TypeBase => success"
? ? /* 0x000002EF 280B00000A? */ IL_0017: call? ? ? void [System.Console]System.Console::WriteLine(string)
? ? /* 0x000002F4 00? ? ? ? ? */ IL_001C: nop
? ? /* (54,13)-(54,14) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002F5 00? ? ? ? ? */ IL_001D: nop
? ? /* (hidden)-(hidden) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002F6 2B0D? ? ? ? */ IL_001E: br.s? ? ? IL_002D
? ? /* (55,18)-(55,19) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002F8 00? ? ? ? ? */ IL_0020: nop
? ? /* (56,17)-(56,66) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x000002F9 7227010070? */ IL_0021: ldstr? ? "foo3 as TypeBase => failure"
? ? /* 0x000002FE 280B00000A? */ IL_0026: call? ? ? void [System.Console]System.Console::WriteLine(string)
? ? /* 0x00000303 00? ? ? ? ? */ IL_002B: nop
? ? /* (57,13)-(57,14) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000304 00? ? ? ? ? */ IL_002C: nop
? ? /* (58,9)-(58,10) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000305 2A? ? ? ? ? */ IL_002D: ret
} // end of method Program::TestAs
// EffectiveCoding03.Program
// Token: 0x06000003 RID: 3 RVA: 0x000020CC File Offset: 0x000002CC
public static void TestAs()
{
? ? Program.TypeSub foo = new Program.TypeSub();
? ? Program.TypeBase foo2 = foo;
? ? bool flag = foo2 != null;
? ? if (flag)
? ? {
? ? ? ? Console.WriteLine("foo3 as TypeBase => success");
? ? }
? ? else
? ? {
? ? ? ? Console.WriteLine("foo3 as TypeBase => failure");
? ? }
}
反編譯結(jié)果顯示var foo3 = foo as TypeBase;被編譯器轉(zhuǎn)換為bool flag = foo2 != null;,同時(shí)也證明了 as 為語法糖,在編譯期間已經(jīng)被寫進(jìn) IL中。
3、強(qiáng)制類型轉(zhuǎn)換
最后來測(cè)試一下 TestConvert 方法。
public static void TestConvert() {
? ? var foo = new TypeSub();
? ? var foo2 = (TypeBase)foo;
? ? Console.WriteLine(foo2);
}
// Token: 0x06000004 RID: 4 RVA: 0x00002108 File Offset: 0x00000308
.method public hidebysig static
? ? void TestConvert () cil managed
{
? ? // Header Size: 12 bytes
? ? // Code Size: 17 (0x11) bytes
? ? // LocalVarSig Token: 0x11000003 RID: 3
? ? .maxstack 1
? ? .locals init (
? ? ? ? [0] class EffectiveCoding03.Program/TypeSub foo,
? ? ? ? [1] class EffectiveCoding03.Program/TypeBase foo2
? ? )
? ? /* (60,42)-(60,43) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000314 00? ? ? ? ? */ IL_0000: nop
? ? /* (61,13)-(61,37) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000315 7307000006? */ IL_0001: newobj? ? instance void EffectiveCoding03.Program/TypeSub::.ctor()
? ? /* 0x0000031A 0A? ? ? ? ? */ IL_0006: stloc.0
? ? /* (62,13)-(62,38) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000031B 06? ? ? ? ? */ IL_0007: ldloc.0
? ? /* 0x0000031C 0B? ? ? ? ? */ IL_0008: stloc.1
? ? /* (64,13)-(64,37) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x0000031D 07? ? ? ? ? */ IL_0009: ldloc.1
? ? /* 0x0000031E 280C00000A? */ IL_000A: call? ? ? void [System.Console]System.Console::WriteLine(object)
? ? /* 0x00000323 00? ? ? ? ? */ IL_000F: nop
? ? /* (65,9)-(65,10) C:\Users\Administrator\source\repos\EffectiveCoding03\EffectiveCoding03\Program.cs */
? ? /* 0x00000324 2A? ? ? ? ? */ IL_0010: ret
} // end of method Program::TestConvert
// EffectiveCoding03.Program
// Token: 0x06000004 RID: 4 RVA: 0x00002108 File Offset: 0x00000308
public static void TestConvert()
{
? ? Program.TypeSub foo = new Program.TypeSub();
? ? Program.TypeBase foo2 = foo;
? ? Console.WriteLine(foo2);
}
看起來, .net 運(yùn)行時(shí)在做類型轉(zhuǎn)換時(shí),只是直接將源對(duì)象直接賦值給目標(biāo)對(duì)象而已?其實(shí)上編譯器對(duì)as操作符、is操作符和強(qiáng)制類型轉(zhuǎn)換都會(huì)對(duì)其合法性進(jìn)行校驗(yàn),他們本質(zhì)上都可以看作是語法糖。于是,我們有了以下總結(jié):
1、is 操作符和 as 操作符均為語法糖;
2、is 操作符可以使代碼更為精簡(jiǎn)。
3、自定義類型轉(zhuǎn)換
為了使 TypeThree 類型支持自定義類型轉(zhuǎn)換,我們現(xiàn)將其改造如下:
public class TypeThree {
? ? public static implicit operator TypeSub(TypeThree typeThree) {
? ? ? ? throw new NotImplementedException();//具體的自定義類型轉(zhuǎn)換實(shí)現(xiàn)
? ? }
}
具體的自定義類型轉(zhuǎn)換請(qǐng)?jiān)趯?shí)際開發(fā)中自行實(shí)現(xiàn)。以上代碼其實(shí)是強(qiáng)制類型轉(zhuǎn)換的運(yùn)算符重載,我們重載了 TypeSub 運(yùn)算符,即可使類似于var foo = (TypeSub) someObject;這樣的代碼可以在編譯器編譯期間通過其合法性校驗(yàn),并在運(yùn)行時(shí)使用重載的自定義類型轉(zhuǎn)換去轉(zhuǎn)換相應(yīng)的類型。下面我們來測(cè)試一下:
public static void TestUserConvert() {
? ? var foo = new TypeThree();
? ? var foo2 = (TypeSub)foo;
? ? Console.WriteLine(foo2);
}
注意var foo2 = (TypeSub)foo;這行代碼若沒有public static implicit operator TypeSub(TypeThree typeThree) 這個(gè)自定義類型轉(zhuǎn)換的話,編譯期間就會(huì)報(bào)錯(cuò),而有了這個(gè)轉(zhuǎn)換,編譯器才知道如何處理它。我們來看看解碼的 IL 驗(yàn)證一下我們的想法:

自定義類型轉(zhuǎn)換的 IL
IL 中調(diào)用自定義類型轉(zhuǎn)換
通過以上2張截圖的紅框部分,我們明顯可以看出運(yùn)行時(shí)在進(jìn)行強(qiáng)制類型轉(zhuǎn)換時(shí)調(diào)用了自定義強(qiáng)制類型轉(zhuǎn)換所提供的轉(zhuǎn)換方法。由于我們有了以下總結(jié):
1、自定義類型轉(zhuǎn)換提供了更為靈活的類型轉(zhuǎn)換方案;
2、is 操作符和 as 操作符沒有任何機(jī)會(huì)執(zhí)行自定義類型轉(zhuǎn)換;
3、強(qiáng)制類型轉(zhuǎn)換需要手工捕獲異常,is 操作符和 as 操作符只需要進(jìn)行 null 判定。
4、循環(huán)中的類型轉(zhuǎn)換問題
循環(huán)中的類型轉(zhuǎn)換問題和強(qiáng)制類型轉(zhuǎn)換基本一致,我們看一下示例:
private static IEnumerable<TypeThree> GetTypeThrees() {
? ? //僅為測(cè)試使用
? ? yield return new TypeThree();
? ? yield return new TypeThree();
? ? yield return new TypeThree();
}
public static void TestIteration() {
? ? var threes = GetTypeThrees();
? ? foreach (TypeSub sub in threes) {
? ? ? ? Console.WriteLine(sub.ToString());
? ? }
}
以上迭代中的代碼與以下代碼基本等價(jià):
public static void TestIteration() {
? ? var threes = GetTypeThrees();
? ? var it = threes.GetEnumerator();
? ? while (it.MoveNext()) {
? ? ? ? var tp = (TypeSub)it.Current;
? ? ? ? Console.WriteLine(tp.ToString());
? ? }
}

解碼后的 IL 中顯示,foreach (TypeSub sub in threes)與普通的類型轉(zhuǎn)換并無二致。
5、結(jié)合泛型和Linq進(jìn)行類型轉(zhuǎn)換
結(jié)合泛型和 Linq 進(jìn)行類型轉(zhuǎn)換時(shí)需要注意的是,Linq 本質(zhì)上是一系列定義好的擴(kuò)展方法,所以結(jié)合 Linq 使用類型轉(zhuǎn)換時(shí),無需提供自定義的類型轉(zhuǎn)換方法也可以被順利編譯。但是要小心的是,如果被轉(zhuǎn)換的類型不是源類型的子類或其它兼容數(shù)據(jù)類型,則可能導(dǎo)致運(yùn)行時(shí)異常。
public static void TestLinq() {
? ? var threes = GetTypeThrees();
? ? var result = threes.Cast<TypeSub>();
}
以上代碼中的var result = threes.Cast();,無論是否提供public static implicit operator TypeSub(TypeThree typeThree),均可在編譯時(shí)順利通過。
6、總結(jié)
1、is 操作符和 as 操作符均為語法糖;
2、is 操作符可以使代碼更為精簡(jiǎn);
3、自定義類型轉(zhuǎn)換提供了更為靈活的類型轉(zhuǎn)換方案;
4、is 操作符和 as 操作符沒有任何機(jī)會(huì)執(zhí)行自定義類型轉(zhuǎn)換;
5、強(qiáng)制類型轉(zhuǎn)換需要手工捕獲異常,is 操作符和 as 操作符只需要進(jìn)行 null 判定;
6、Linq 中的 Cast of T 轉(zhuǎn)換不需要自定義類型轉(zhuǎn)換重載,但必須是源類型的子類或其它兼容數(shù)據(jù)類型。
開發(fā)人員應(yīng)牢記以上開發(fā)守則,否則,人民群眾會(huì)仇恨你,你的朋友和家人也會(huì)嘲笑你、唾棄你。
該系列文章由比特飛原創(chuàng)發(fā)布,計(jì)劃用半年時(shí)間寫完全50篇文章,為大家提供編寫高質(zhì)量代碼的一般準(zhǔn)則。
本文由?比特飛?原創(chuàng)發(fā)布,歡迎大家踴躍轉(zhuǎn)載。
轉(zhuǎn)載請(qǐng)注明本文地址:https://www.byteflying.com/archives/6710。