[C#][Tips]型別轉換
型別轉換我想大家都常用,由於最近剛好碰到轉型上的問題,就順便整理了一下。
大概整理了隱含轉換和明確轉換。
隱含轉換(implicit conversions):
基本上是默認許可的,C# compiler無須詳細檢查就能安全轉換型別。
如int轉float過程中資料不會遺失一般也不會失敗,為什麼呢?因為在不管什麼型別,
都以bit儲存(0和1),只要目標型別有足夠的空間大部分結果都是正確的
(但也有可能與期望的不同,如精準度變低)。
Example:
class Program
{
static void Main(string[] args)
{
byte i = 32;
Console.WriteLine("i={0}",i);
ushort j = i;
Console.WriteLine("j={0}", j);
j = 65535;
Console.WriteLine("j={0}", j);
double k = j;
Console.WriteLine("k={0}", k);
Console.ReadLine();
}
}
結果:
但修改了j=65536 compiler就會出現如下錯誤(說明兩者不存在隱含轉型)
Example:
int x = 1234566799;
Console.WriteLine("x={0}", x);
float y = x;
Console.WriteLine("y={0}", y);
結果:
隱含參考轉換:
針對參考型別 (定義為類別、委派、陣列或介面的型別=Reference Type),
將類別轉換為其任何直接或間接基底類別或介面時,一律會使用隱含轉換。
不必使用特殊語法,因為衍生類別一定包含基底類別的所有成員。
Example:正常編譯
class BkClass {}
class CarClass : BkClass {}
BkClass[] bkclassar = new BkClass[4];
CarClass[] carclassar = new CarClass[4];
bkclassar = carclassar;
Example:編譯失敗(因為不是reference type)
ushort[] arr1 = new ushort[4];
int[] arr2 = new int[4];
arr1 = arr2;
我們也可用以下方式查看原生型別
byte[] bytearr = new byte[4];
Console.WriteLine(bytearr);
long[] longarr = new long[4];
Console.WriteLine(longarr);
float[] floatarr=new float[4];
Console.WriteLine(floatarr);
int[] intarr=new int[4];
Console.WriteLine(intarr);
string[] stringarr = new string[4];
Console.WriteLine(stringarr);
結果:
隱含列舉轉換:
在列舉轉換中,允許十進制0轉換成任何列舉型別,其他所對應的整數則不存在隱含轉換。
enum week {
Sunday,Monday,Tuesday,Wendnesday,Thursday,Friday,Saturday
}
week myday;
myday = 0;
Console.WriteLine(myday);
Console.ReadLine();
結果:
但如果修改myday=1就會出現以下錯誤
明確轉換(explicit conversions):
可以稱為強制轉換或顯示轉換,剛好和隱含轉換相反。
byte mybyte;
ushort myushort = 100;
mybyte = (byte)myushort;
Console.WriteLine(myushort);
Console.WriteLine(mybyte);
Console.ReadLine();
結果:
如果修改成myushort=270將造成資料遺失
byte mybyte;
ushort myushort = 270;
mybyte = (byte)myushort;
Console.WriteLine(myushort);
Console.WriteLine(mybyte);
Console.ReadLine();
結果:
查看二進制就知道原因了(最左邊的1不見了)。
270=100001110
14 = 000001110
當我們要強制轉換時(如果不確定是否會發生溢位),建議可以先使用checked來檢查。
改寫如下將出現OverflowException。
byte mybyte;
ushort myushort = 270;
mybyte = checked((byte)myushort);
Console.WriteLine(myushort);
Console.WriteLine(mybyte);
結果:
如果使用unckecked也會導致資料遺失。
當然我們也可以設定VS IDE在建置時自動執行checked(除非明確使用unchecked)
明確列舉轉換:
實際上是處理列舉成員型別和相對應型別之間的隱含或明確轉換。
改一下隱含列舉列子
enum week {
Sunday,Monday,Tuesday,Wendnesday,Thursday,Friday,saturday
}
week myday;
myday = (week)6;
Console.WriteLine(myday);
結果:
結論:
我們常常使用轉型,雖然C# compiler帶給我們在程式編寫上強大的靈活性和方便性,
但不當的使用有可能造成資料遺失或引發異常,所以還是得小心注意使用。
更詳細的資訊可查看MSDN Library。