從IL看強制轉換和is,as

2021-06-16 20:12:21 字數 1964 閱讀 4025

1.強制型別轉換。

注意:下面的所有的il**都是release版,並且優化之後的。

is和as的作用不多說,下面主要從il角度來看一下他們的工作原理。

請看如下**:

class casttest

}

然後使用ildasm檢視他的il**,如下:

首先,使用ldstr指令將物件「ok「的引用載入到棧上,然後使用stloc.0指令將引用賦值給變了o。因此,ldstr  「ok」 和stloc.0相當於object  o=」ok「。

注:stloc.0指令的全寫為:「store the value on the top of stack  to  thefirst local. 「意思將棧頂元素儲存到第乙個區域性變數中。il棧分為三個部分:引數區,區域性變數區,計算棧。可以將他們分別看成乙個陣列,要訪問他們都需要通過下標索引,譬如想要將第乙個區域性變數載入到計算棧上,就可以使用ldloc.0指令,其中0就是索引0.如果想要將計算棧頂元素儲存到區域性變數區中的第0個區域性變數就可以使用stloc.0指令。

接下來,ldloc.0指令將變數o載入到計算棧中,然後使用castclass指令將o強制轉換為system.string。

這裡的核心指令是castclass,需要注意這個指令在轉換不成功的時候,會丟擲乙個invalidcastexception異常。因此,在高階語言中一般建議不使用強制型別轉換,而是使用可替代的is或者as關鍵字。

2.is和as

由於使用強制轉換可能會在執行的時候丟擲乙個異常,所以作為替代,c#提供了另一種型別轉換方式,使用這種轉換方式,即使在轉換不成功的時候,也不會丟擲乙個異常,這就是使用關鍵字is和as來實現的。

修改上述**如下:

class casttest

}

編譯後,檢視他的il**,如下:

這一次,c#沒有生成castclass指令,而是生成了乙個isinst指令。這個指令彈出棧頂元素,然後將其準換為system.string型別,如果轉換成功那麼就將轉換後的型別壓入棧頂,如果轉換失敗,那麼就將乙個null入棧,而不是丟擲乙個異常。

因此,我們只需要檢查結果是否為null,就可以知道轉換是否成功。

事實上,編譯器為不僅僅為as關鍵字生成了isinst指令,也為is關鍵字生成了isinst。將上述**修改如下:

class casttest}}

il**如下:

由於is關鍵字需要乙個判斷,所以編譯器不僅僅會生成乙個isinst指令,緊接著還會使用b***lse.s指令來判斷轉換的結果是否為flase(flase和null都是乙個0),如果轉換失敗就跳轉到il_001b處,否則繼續執行下面的指令。

正如你所看到的,編譯器會為as關鍵字生成乙個isinst指令,為is關鍵字生成兩個指令:isinst和b***lse。但是,我們一般不會在源**直接使用as關鍵字,而是在as之後,在來乙個if語句來判斷換轉是否成功。如下:

class casttest}}

class casttest}}

上面**只轉換一次(string str=o as string)。

再看下面**:

class casttest}}

這裡卻需轉換兩次,一處在o is string,這裡主要使用isinst指令;一處在(string)o,這裡使用castclass指令。

C的強制轉換和C 的強制轉換

c的強制轉換 type 其中,type為型別描述符,如int,float等。為表示式。經強制型別轉換運算子運算後,返回乙個具有type型別的數值,這種強制型別轉換操作並不改變運算元本身,運算後運算元本身未改變,例如 int nvar 0xab65 char cchar char nvar 上述強制型...

java自動轉換和強制轉換

資料型別的轉換,分為自動轉換和強制轉換。自動轉換是程式在執行過程中 悄然 進行的轉換,不需要使用者提前宣告,一般是從位數低的型別向位數高的型別轉換 強制型別轉換則必須在 中宣告,轉換順序不受限制。自動資料型別轉換 自動轉換按從低到高的順序轉換。不同型別資料間的優先關係如下 低 高 byte,shor...

精度 自動轉換和強制轉換

資料型別的轉換,分為自動轉換和強制轉換。自動資料型別轉換 自動轉換按從低到高的順序轉換。不同型別資料間的優先關係如下 低 高 byte,short,char int long float double 轉換列表 運算元一 運算元二 轉換後型別 byte short char intint byte ...