一,在程序中我們經常會遇到:無法將類型“XXX”隱式裝換為“XXX”,如下例子:
static void Main(string[] args) { int i; i = "Hello World"; }
那這是什么原因呢?
由於 C# 是在編譯時靜態類型化的,因此變量在聲明后就無法再次聲明,或者無法用於存儲其他類型的值,除非該類型可以轉換為變量的類型。 例如,不存在從整數到任意字符串的轉換。 因此,在將 i
聲明為整數后,無法將字符串“Hello World”賦予它.
二, 在 C# 中,常見的兩種類型的轉換:
1》隱式轉換:
1,系統默認的、不需要加以聲明就可以進行的轉換,在隱式轉換過程中,編譯器無需對轉換進行詳細檢查就能夠安全地執行轉換。
2,該轉換是一種類型安全的轉換,不會導致數據丟失,因此不需要任何特殊的語法。
PS:示例包括從較小整數類型到較大整數類型的轉換(從int到float的轉換)以及從派生類到基類的轉換(子類到父類)。
2》顯式轉換(強制轉換):
1,顯式轉換需要用戶明確地指定轉換的類型
2,顯式轉換需要強制轉換運算符。 在轉換中可能丟失信息時或在出於其他原因轉換可能不成功時,必須進行強制轉換。
PS:典型的示例包括從數值到精度較低或范圍較小的類型的轉換(float到int的轉換)和從基類實例到派生類的轉換(父類到子類)。
三,那為什么隱式轉換不會導致數據丟失,而顯示轉換會?
1》隱式轉換不會丟失原因:對於內置數值類型,如果要存儲的值無需截斷或四舍五入即可適應變量,則可以進行隱式轉換。
例如,long 類型的變量(8 字節整數)能夠存儲 int(在 32 位計算機上為 4 字節)可存儲的任何值。 在下面的示例中,編譯器先將右側的值隱式轉換為 long
類型,再將它賦給 longNum
。
int intnum = 68564235; long longNum = intnum; Console.WriteLine(longNum);
2》顯示轉換如下:
//錯誤:無法將類型“double”隱式轉換為“int”。存在一個顯式轉換(是否缺少強制轉換?) double x = 1234.4567; int a; a = x; Console.WriteLine(a);
下面的程序將 double 強制轉換為 int。 如不強制轉換則該程序不會進行編譯,並有無法將類型“double”隱式轉換為“int”。存在一個顯式轉換(是否缺少強制轉換?)
這樣的意思是:當我們在將精度大的轉換為精度小的(或者父類轉換為子類時),這時就是顯示轉換,但是當我們存在顯示轉換而沒有強制轉換的時候編輯就會報錯,如下解決:
double x = 1234.4567; int a; a = (int)x; Console.WriteLine(a);
但是這個時候,我們輸出的值就是int的精度的值,就是1234
三,那引用類型的隱式和顯示轉換又是怎樣的呢?如下例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TypeDemo2 { class Program { static void Main() { //派生類是繼承基類過來的,所有基類有的定義它都會有,所以這樣的隱式轉換是被認為合法的 Animal a = new Dog(); a.Eat(); //然而基類類型不能隱式轉換為派生類,因為派生類中的成員定義在基類中是不一定存在的 //Dog d = new Animal(); //同時基類類型不能顯示轉換為派生類,強轉也是報錯的 //Animal aa = new Animal(); //Dog d = (Dog)aa; //d.Eat(); //在理解隱式和顯式的時候還有一個誤區,如下,神奇的事發生了,不是基類不能隱式轉換為派生類么? //以下代碼的理解是:雖然類型是Animal,但是他的實際的值還是指向余內存的Dog這塊空間,所以當你使用AS dog時候不會報錯 Animal a1 = new Dog(); Dog d = a1 as Dog; //a1.Say(); //這樣寫報錯 d.Eat(); d.Say(); } } class Animal { public void Eat() { Console.WriteLine("吃!!!"); } } class Dog : Animal { public void Say() { Console.WriteLine("汪汪"); } } }
綜上:引用類型的隱式轉換是合法的(派生類轉換成基類,子類轉換成父類),而反之報錯,因為派生類成員定義不一定子在基類中存在