略講型別轉換

2021-06-16 23:46:49 字數 2719 閱讀 9271

一些常見的問題:

1.      為什麼c#不能講字串直接強制轉換為int,而是額外提供乙個system.convert.toint32()方法。

2.      幾種常見轉換之間的效能對比。

1.      關於溢位,如何檢查溢位。

1.基元型別之間的型別轉換。

需要注意的是,基元型別之間的轉換是不會丟擲異常的,這一點很重要,譬如int可以轉換為byte(溢位也算)而不會丟擲任何異常,當然你可能會說,這可能會產生溢位!是的,當int大於256時,確實會產生溢位,但是這裡是從計算機位級考慮資料轉換的,所以這裡溢位也是正確的。

il中有一些列轉換指令可以進行基元型別之間的轉換,這些指令不會丟擲任何異常。譬如conv.i1可以將乙個其他值轉換為byte。譬如下面這段**就會使用這個指令:

byte c=(byet)0x12345;

c最終是什麼呢?可以輸出一下試試。

預設情況下,上述**是不會丟擲異常的,這是因為編譯器預設生成了conv.i1指令,而conv.i1指令在發生溢位時是不會丟擲任何異常的,如果想要在發生溢位時得到乙個通知,可以使用conv.i1,這條指令在溢位時會丟擲乙個overflowexception異常。

要想要上述**丟擲異常,如下所示:

checked

byte c=(byte)0x12345;

這時候會丟擲乙個overflowexception異常,這在除錯的時候非常有用。

關於這方面的內容,請見如下部落格:

注意:位級別轉換就是在轉換的過程中位模式不變,只是進行相應的符號擴充套件(在前面填充0或者1),或者直接截斷處理。將byte型別的256轉換為int型別還是256他們的位模式從

1111 1111到1111 11111111 1111 1111 1111 1111 1111。也就是將1111 1111前面所有位都符號擴充套件到1.

2.   引用型別之間的型別轉換

上面所說的是基元型別之間的轉換,他們之間的轉換都是從位級考慮的。對於引用型別之間的轉換則不同。

引用型別之間的轉換最終會轉換到il的castclass指令。這條之間可以將乙個引用型別轉換為另乙個引用型別,前提是二者必須具有繼承關係,如果二者沒有繼承關係,那麼就會丟擲乙個invalidcastexception異常。

可以看到,雖然在c#中,對於基元型別和引用該型別之間的的強制型別轉換,都是通過強制型別轉換符(也就是那個括號)來實現的,但是在不同的語義下會產生不同的指令。對於機緣型別的型別轉換會產生上面所說的指令,對於引用型別之間的轉換會產生castclass指令。

如果不想再轉換的過程中跑出乙個異常,那麼就可以使用is和as操作符。

3.   拆箱和裝箱

拆箱和裝箱也可以算是一種型別轉換吧!畢竟從值型別和引用型別是兩種不同的型別。這裡不打算講解裝箱和拆箱的細節問題,而是討論轉換過程中可能會出現的異常,從而不至於在執行時丟擲異常時而不知所措。

在c#中,對於裝箱而言,是不會丟擲任何異常的,因為編譯器限制了裝箱的條件:要想將乙個值型別裝箱成引用型別,這個值型別必須是引用型別的派生類。所以這裡,裝箱是不會產生任何異常的。

但是,在拆箱的過程中則不然,拆箱可能會出現令人討厭的invalidcastexception異常。如果將乙個int裝箱之後,拆箱成乙個byte就會丟擲那個異常。請看如下**:

int i=12;

objecta = i;

byteb = (byte)a;

毫無疑問,這段**在執行的時候會丟擲乙個invalidexception異常。int裝箱之後會在堆中建立乙個物件,這個物件的值也是12。然後我們做的是將這個堆中的物件拆箱成byte,clr認為這是乙個錯誤,他會丟擲invalidexception異常,來阻止我們這麼做。

當然了,如果我們就是想將a拆箱成byte,怎麼做呢?要想達到這種效果可以就**進行入下修該:

int i=12;

objecta = i;

byteb = (byte)(int))a;

現在編譯執行,正常。

注:將乙個

int型別進行裝修的時候,會在堆中建立乙個物件,這個物件不僅包含原來值的乙個副本,還包含乙個型別資訊。就那上面的例子,

12裝箱會在堆中產生乙個物件,這個物件的值是

12,除此之外,這個物件還包含乙個記錄,來指定這是乙個

int型別。拆箱的時候,會檢查這個記錄和目標型別時否匹配,如果不匹配,就會丟擲乙個

invalidcastexception

異常。4.   特殊的型別轉換

嚴格的說,這裡並不是型別轉換,但是他們達到了型別轉換的效果,所以稱他們為特殊的型別轉換。

object的tostring方法。

convert的一些列to***x方法。

有時候,使用者在介面中輸入了乙個字串12,然後我們想要將其轉換為整數型別,從而執行基本算術運算。想要將乙個字串轉換為乙個int,用普通做法是做不到的。你不能直接將字串12轉換為整數12,編譯器不讓你做,如下:

string  input=「12「;

int  age=(string)input;

如果寫出如上**,編譯器肯定不讓過。因為input和age具有不同的位級表示:

input位級表示:

age的位級表示:

如果將input轉換為age,將轉換成了什麼?從位級角度看,這完全沒有任何意義。顯然普通的做法是無法將string轉換為int的。

c#中提供了convert.toint32(string input)方法,該方法可以分析引數input,發現裡面儲存的是49,50(utf8編碼),並將49,50對映到整數12,然後將返回整數12.

資料庫分類略講

1.資料庫的介紹 資料庫就是儲存和管理資料的倉庫,資料按照一定的格式進行儲存,使用者可以對資料庫中的資料進行增加 修改 刪除 查詢等操作。2.資料庫的分類 關係型資料庫 是指採用了關係模型來組織資料的資料庫,簡單來說,關係模型指的就是二維 模型,好比excel檔案中的 強調使用 的方式儲存資料。關係...

void (指標)的型別轉換 專講

指標是乙個特殊的變數,它裡面儲存的數值被解釋成為記憶體裡的乙個位址,所以不管你儲存的是int指標 float指標 long指標,對於儲存指標的記憶體來說都是分配同樣大小的記憶體的,這也為使用void指標可以儲存任意型別的指標打下了基礎,但是注意在使用void指標,要將其強制轉換為具體的指標型別,詳解...

2020 02 09日常總結 dp例題略講

原題 鏈結 原題鏈結 點此進入原題面 題目 大意 color 題目大意 有乙個色子,每個面上有乙個數字,x xx對面是7 x 7 x7 x,我們可以把色子旋轉90 9090 度,然後把頂面數字加入得分,求最少幾步剛剛達到n nn分。若無解,輸出 1。思路 color 思路 很明顯的一道dpdp dp...