編寫高質(zhì)量代碼的50條黃金守則-Day 03(首選is或as而不是強(qiáng)制類型轉(zhuǎn)換)

本文由比特飛原創(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。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容