[C#][Tips]型別轉換

  • 11384
  • 0
  • C#
  • 2009-11-22

[C#][Tips]型別轉換

型別轉換我想大家都常用,由於最近剛好碰到轉型上的問題,就順便整理了一下。

大概整理了隱含轉換和明確轉換。

 

隱含轉換(implicit conversions):

基本上是默認許可的,C# compiler無須詳細檢查就能安全轉換型別。

如int轉float過程中資料不會遺失一般也不會失敗,為什麼呢?因為在不管什麼型別,

都以bit儲存(0和1),只要目標型別有足夠的空間大部分結果都是正確的

(但也有可能與期望的不同,如精準度變低)。

隱含數值轉換表:

image

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();
        }
    }

結果:

image

但修改了j=65536 compiler就會出現如下錯誤(說明兩者不存在隱含轉型)

image

Example: 

int x = 1234566799;
Console.WriteLine("x={0}", x);
float y = x;
Console.WriteLine("y={0}", y);

結果:

image

 

含參考轉換:

針對參考型別 (定義為類別委派、陣列或介面的型別=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;

image

我們也可用以下方式查看原生型別 

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);

結果:

image

列舉轉換:

在列舉轉換中,允許十進制0轉換成任何列舉型別,其他所對應的整數則不存在隱含轉換。 

enum week { 
Sunday,Monday,Tuesday,Wendnesday,Thursday,Friday,Saturday            
}
week myday;
myday = 0;
Console.WriteLine(myday);
Console.ReadLine();

結果:

image

但如果修改myday=1就會出現以下錯誤

image

 

明確轉換(explicit conversions):

可以稱為強制轉換或顯示轉換,剛好和隱含轉換相反。

明確數值轉換表:

image

 

byte mybyte;
ushort myushort = 100;
mybyte = (byte)myushort;
Console.WriteLine(myushort);
Console.WriteLine(mybyte);
Console.ReadLine();  

結果:

image

如果修改成myushort=270將造成資料遺失 

byte mybyte;
ushort myushort = 270;
mybyte = (byte)myushort;
Console.WriteLine(myushort);
Console.WriteLine(mybyte);
Console.ReadLine();  

結果:

image

查看二進制就知道原因了(最左邊的1不見了)。

270=100001110

14 = 000001110

當我們要強制轉換時(如果不確定是否會發生溢位),建議可以先使用checked來檢查。

改寫如下將出現OverflowException。 

byte mybyte;
ushort myushort = 270;
mybyte = checked((byte)myushort);
Console.WriteLine(myushort);
Console.WriteLine(mybyte);

結果:

image

如果使用unckecked也會導致資料遺失。

當然我們也可以設定VS IDE在建置時自動執行checked(除非明確使用unchecked)

image image image

明確列舉轉換:

實際上是處理列舉成員型別和相對應型別之間的隱含或明確轉換。

改一下隱含列舉列子

enum week { 
Sunday,Monday,Tuesday,Wendnesday,Thursday,Friday,saturday            
}
week myday;
myday = (week)6;
Console.WriteLine(myday);

結果:

image

 

結論:

我們常常使用轉型,雖然C# compiler帶給我們在程式編寫上強大的靈活性和方便性,

但不當的使用有可能造成資料遺失或引發異常,所以還是得小心注意使用。

更詳細的資訊可查看MSDN Library。 

轉型和型別轉換 (C# 程式設計手冊)