C#中的型別轉換大總結
使用C#一個最常見的問題便是各種型別間的轉換。我們知道,C#中的型別分為值型別和引用型別兩大類。但是,有關它們間各自轉換的細節描述在網上很少得到詳細的回答。現在,我結合搜尋到的部分資料整理如下:
1,問題
c#中型別轉換的有兩種,()轉換和convert轉換。 我想知道的是這兩個轉換的區別 還有就是()轉換我用了發現好多不能轉換過來,但是convert是萬能轉換的, 那什麼時候該用()什麼時候該用convert呢? 最後問下子,把int sum怎麼用()轉換成float型別? 請詳細說明,最好有舉例。 |
解答:
(1)這兩個方法的最大不同是它們對null值的處理方法: 沒搞清楚Convert.ToInt32和int.Parse()的細細微區別時千萬別亂用,否則可能會產生無法預料的結果, 舉例來說:假如從url中取一 個引數page的值,我們知道這個值是一個int, 所以即可以用 Convert.ToInt32(Request.QueryString["page"]), 也可以 用,int.Parse(Request.QueryString["page"]),但是如果page這個引數在url中不存在, 那麼前者將返回0,0可能是一個有效的值,所以你不知道url中原來根本就沒有這個引數而繼續進行下一下 的處理,這就可能產生意想不到的效果,而用後一種辦法的話沒有page這個引數會丟擲異常, 我們可以捕獲異常然後再做相應的處理,比如提示使用者缺少引數,而不是把引數值當做0來處理。 (2)還有一點區別就是 而 5.5 轉換為 6。 不過4.6可以轉換為5,4.4轉換為4 c. (int)4.6 = 4 也就是*.Parse(string)括號中的一定要是string. |
2,問題:
如何使用 as和 is運算子安全地進行強制轉換? |
解答:首先,在MSDN(http://msdn.microsoft.com/zh-cn/library/cc488006.aspx)給出的解釋非常簡單,過於簡單。更詳細的解釋如下:
在程式中,進行型別轉換是常見的事。那麼在C#中支援以前語言的型別轉換方法,
即用型別名進行強行轉換,例如:
object objTest =new NewType();
NewType newValue = (NewType)objTest;
但是這樣轉換,有個嚴重的問題,就是在把objTest強轉換成NewType型別物件的時候,
這個過程是不安全的,因此需要用try-catch語句來進行保護。這樣一來,
比較安全的程式碼方式應該如下所示。
object objTest =new NewType();
NewType newValue =null;
{
newValue = (NewType)objTest;
}
catch( Exception err )
{
MessageBox.Show( err.Message );
}
但是如上的寫法在C#中已經屬於過時的寫法,而且也屬於比較低效的寫法。
在C#中比較高效而且安全的寫法,應該用as操作符,那麼完成如上類似功能的正確程式碼應該如下。
object objTest =new NewType();
NewType newValue = objTest as NewType;
那麼很明顯,如上的寫法首先看起來很簡便,至少程式碼數量和強轉方式一樣。至於安全性,
對於as操作符來說,它不會做過的轉換操作,當需要轉換物件的型別屬於轉換目標類
型或者轉換目標型別的派生型別的時候,那麼此轉換操作才能成功,而且並不產生新
的物件。因此用as來進行型別轉換使安全的。為什麼用as操作符進行型別轉換的效率要高於
老式的型別轉換的,因為用as操作符進行轉換就如前面所說的,首先判斷當前物件的型別,
當型別滿足要求後才進行轉換。而傳統的型別轉換方式,是用當前物件直接去轉換,而且
為了保護轉換成功,要加上try-catch,這就決定了它的效率不會高於as操作符的效率。
要注意的時候,不管用傳統方式,還是用as操作符進行型別轉換之後,在使用之前,
需要進行判斷轉換是否成功,如下:
if( newValue!=null)
{
//Work with the object named "newValue"
}
但是,使用as操作符有如下幾點限制。
第一個就是,不用在型別之間進行型別轉化,即如下編寫就會出現編譯錯誤。
NewType newValue =new NewType();
NewType1 newValue = newValue as NewType1;
第二個就是,不能應用在值型別資料,即不能如下寫(也會出現編譯錯誤)。
object objTest = 11;
int nValue = objTest as int;
對於第一點所提的,可以用傳統的型別轉換方式來完成,但是光用如下的方式,是不能正確完成。
NewTypeOne newTestOne =new NewTypeOne();
NewTypeTwo newTestTwo = (NewTypeTwo)newTestOne;
但是光如上寫是不能完成的,要想使如上的操作能正確完成,在原有型別中增加型別轉換
操作符函式,即需要完成類似如下的程式碼。
public class NewTypeOne
{
public static explicit operator NewTypeTwo( NewTypeOne objTest )
{
//Convert object into new type
}
}
對於第二點所提的,在C#中可以使用is操作符,再加上老式的型別轉換操作,就可以安全完成
轉換,那麼要完成如上操作,正確的寫法如下。
object objTest = 11;
if( objTest is int)
{
int nValue = (int)objTest;
}
除了如上兩點限制外,在用as操作符來進行型別轉換的時候,有個細微的問題。在前面
所說的,用as來進行型別轉換的時候,所要轉換的物件型別必須是目標型別或者轉換目
標型別的派生型別,那麼這樣就有個問題,即用as操作符來進行型別轉換的時候無法轉
換成正確的型別,也就是說本來應該轉換成子型別,卻轉換成了父型別。但是我並不認
為這是個嚴重問題,因為在用as操作符來進行型別轉換的時候,如何選擇目標型別在編
碼的時候已經很明確了,即用父型別作為目標型別,那麼型別轉換的目的就是轉換成父
型別物件進行操作;反之亦然。
在C#中已經提供了一個很好的型別轉換方式,那麼在進行型別轉換的時候,可以按照如
下的方式進行選擇。
型別轉換 |
使用選擇 |
Object =>已知引用型別 |
使用as操作符來完成 |
Object =>已知值型別 |
先使用is操作符來進行判斷,再用型別強轉方式進行轉換 |
已知引用型別之間轉換 |
首先需要相應型別提供轉換函式,再用型別強轉方式進行轉換 |
已知值型別之間轉換 |
最好使用系統提供的Convert類所涉及的靜態方法 |