一,在程序中我們經(jīng)常會(huì)遇到:無法將類型“XXX”隱式裝換為“XXX”,如下例子:
static void Main(string[] args)
{
int i;
i = "Hello World";
}
那這是什么原因呢?
由于 C# 是在編譯時(shí)靜態(tài)類型化的,因此變量在聲明后就無法再次聲明,或者無法用于存儲(chǔ)其他類型的值,除非該類型可以轉(zhuǎn)換為變量的類型。 例如,不存在從整數(shù)到任意字符串的轉(zhuǎn)換。 因此,在將 i 聲明為整數(shù)后,無法將字符串“Hello World”賦予它.
二, 在 C# 中,常見的兩種類型的轉(zhuǎn)換:
1》隱式轉(zhuǎn)換:
1,系統(tǒng)默認(rèn)的、不需要加以聲明就可以進(jìn)行的轉(zhuǎn)換,在隱式轉(zhuǎn)換過程中,編譯器無需對(duì)轉(zhuǎn)換進(jìn)行詳細(xì)檢查就能夠安全地執(zhí)行轉(zhuǎn)換。
2,該轉(zhuǎn)換是一種類型安全的轉(zhuǎn)換,不會(huì)導(dǎo)致數(shù)據(jù)丟失,因此不需要任何特殊的語法。
PS:示例包括從較小整數(shù)類型到較大整數(shù)類型的轉(zhuǎn)換(從int到float的轉(zhuǎn)換)以及從派生類到基類的轉(zhuǎn)換(子類到父類)。
2》顯式轉(zhuǎn)換(強(qiáng)制轉(zhuǎn)換):
1,顯式轉(zhuǎn)換需要用戶明確地指定轉(zhuǎn)換的類型
2,顯式轉(zhuǎn)換需要強(qiáng)制轉(zhuǎn)換運(yùn)算符。 在轉(zhuǎn)換中可能丟失信息時(shí)或在出于其他原因轉(zhuǎn)換可能不成功時(shí),必須進(jìn)行強(qiáng)制轉(zhuǎn)換。
PS:典型的示例包括從數(shù)值到精度較低或范圍較小的類型的轉(zhuǎn)換(float到int的轉(zhuǎn)換)和從基類實(shí)例到派生類的轉(zhuǎn)換(父類到子類)。
三,那為什么隱式轉(zhuǎn)換不會(huì)導(dǎo)致數(shù)據(jù)丟失,而顯示轉(zhuǎn)換會(huì)?
1》隱式轉(zhuǎn)換不會(huì)丟失原因:對(duì)于內(nèi)置數(shù)值類型,如果要存儲(chǔ)的值無需截?cái)嗷蛩纳嵛迦爰纯蛇m應(yīng)變量,則可以進(jìn)行隱式轉(zhuǎn)換。
例如,long 類型的變量(8 字節(jié)整數(shù))能夠存儲(chǔ) int(在 32 位計(jì)算機(jī)上為 4 字節(jié))可存儲(chǔ)的任何值。 在下面的示例中,編譯器先將右側(cè)的值隱式轉(zhuǎn)換為 long 類型,再將它賦給 longNum。
int intnum = 68564235;
long longNum = intnum;
Console.WriteLine(longNum);
2》顯示轉(zhuǎn)換如下:
//錯(cuò)誤:無法將類型“double”隱式轉(zhuǎn)換為“int”。存在一個(gè)顯式轉(zhuǎn)換(是否缺少強(qiáng)制轉(zhuǎn)換?)
double x = 1234.4567;
int a;
a = x;
Console.WriteLine(a);
下面的程序?qū)?double 強(qiáng)制轉(zhuǎn)換為 int。 如不強(qiáng)制轉(zhuǎn)換則該程序不會(huì)進(jìn)行編譯,并有無法將類型“double”隱式轉(zhuǎn)換為“int”。存在一個(gè)顯式轉(zhuǎn)換(是否缺少強(qiáng)制轉(zhuǎn)換?)
這樣的意思是:當(dāng)我們?cè)趯⒕却蟮霓D(zhuǎn)換為精度小的(或者父類轉(zhuǎn)換為子類時(shí)),這時(shí)就是顯示轉(zhuǎn)換,但是當(dāng)我們存在顯示轉(zhuǎn)換而沒有強(qiáng)制轉(zhuǎn)換的時(shí)候編輯就會(huì)報(bào)錯(cuò),如下解決:
double x = 1234.4567;
int a;
a = (int)x;
Console.WriteLine(a);
但是這個(gè)時(shí)候,我們輸出的值就是int的精度的值,就是1234
*拓展知識(shí)
三、那引用類型的隱式和顯示轉(zhuǎn)換又是怎樣的呢?如下例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TypeDemo2
{
class Program
{
static void Main()
{
//派生類是繼承基類過來的,所有基類有的定義它都會(huì)有,所以這樣的隱式轉(zhuǎn)換是被認(rèn)為合法的
Animal a = new Dog();
a.Eat();
//然而基類類型不能隱式轉(zhuǎn)換為派生類,因?yàn)榕缮愔械某蓡T定義在基類中是不一定存在的
//Dog d = new Animal();
//同時(shí)基類類型不能顯示轉(zhuǎn)換為派生類,強(qiáng)轉(zhuǎn)也是報(bào)錯(cuò)的
//Animal aa = new Animal();
//Dog d = (Dog)aa;
//d.Eat();
//在理解隱式和顯式的時(shí)候還有一個(gè)誤區(qū),如下,神奇的事發(fā)生了,不是基類不能隱式轉(zhuǎn)換為派生類么?
//以下代碼的理解是:雖然類型是Animal,但是他的實(shí)際的值還是指向余內(nèi)存的Dog這塊空間,所以當(dāng)你使用AS dog時(shí)候不會(huì)報(bào)錯(cuò)
Animal a1 = new Dog();
Dog d = a1 as Dog;
//a1.Say(); //這樣寫報(bào)錯(cuò)
d.Eat();
d.Say();
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("吃?。?!");
}
}
class Dog : Animal
{
public void Say()
{
Console.WriteLine("汪汪");
}
}
}
綜上:引用類型的隱式轉(zhuǎn)換是合法的(派生類轉(zhuǎn)換成基類,子類轉(zhuǎn)換成父類),而反之報(bào)錯(cuò),因?yàn)榕缮惓蓡T定義不一定子在基類中存在