第四章 C#類型
既然你知道了怎樣創建一個簡單的C#程序我將會給你介紹C#的類型系統在這一章中你學到如何使用不同的值和引用類型加框和消框機制能為你作些什麼盡管這一章的不側重於例子但你可以學到很多重要的信息關於如何創建現成類型的程序
值類型
各種值類型總是含有相應該類型的一個值C#迫使你初始化變量才能使用它們進行計算變量沒有初始化不會出問題因為當你企圖使用它們時編譯器會告訴你 每當把一個值賦給一個值類型時該值實際上被拷貝了相比對於引用類型僅是引用被拷貝了而實際的值仍然保留在相同的內存位置但現在有兩個對象指向了它(引用它)C#的值類型可以歸類如下
簡單類型(Simple types )
結構類型(struct types)
枚舉類型(Enumeration types)
簡單類型
在C#中出現的簡單類型共享一些特性第一它們都是NET系統類型的別名第二由簡單類型組成的常量表達式僅在編譯時而不是運行時受檢測最後簡單類型可以按字面被初始化以下為C#簡單類型歸類
整型
布爾型
字符型 (整型的一種特殊情況)
浮點型
小數型
整型
C#中有個整型 sbyte byte short ushort int uint long ulong 和 char(單獨一節討論)它們具有以下特性
sbyte型為有符號位整數取值范圍在~之間
bytet型為無符號位整數取值范圍在~之間
short型為有符號位整數取值范圍在~之間
ushort型為無符號位整數取值范圍在~之間
int型為有符號位整數取值范圍在~ 之間
uint型為無符號位整數取值范圍在 ~ 之間
long型為位有符號整數取值范圍在~ 之間
ulong型為位無符號整數取值范圍在 ~ 之間
VB和C程序員都可能會對int和long數據類型所代表的新范圍感到驚訝和其它的編程語言相比在C#中int不再取決於一個機器的字(word)的大小而long被設成位
布爾型
布爾數據類型有true和false兩個布爾值可以賦於true或false值給一個布爾變量或可以賦於一個表達式其所求出的值等於兩者之一
bool bTest = ( > )
與C和C++相比在C#中true值不再為任何非零值不要為了增加方便而把其它整型轉換成布爾型
字符型
字符型為一個單Unicode 字符一個Unicode字符位長它可以用來表示世界上多種語言可以按以下方法給一個字符變量賦值
char chSomeChar = A
除此之外可以通過十六進制轉義符(前綴\x)或Unicode表示法給變量賦值(前綴\u)
char chSomeChar = \x
char chSomeChar = \u
不存在把char轉換成其它數據類型的隱式轉換這就意味著在C#中把一個字符變量當作另外的整數數據類型看待是行不通的——這是C程序員必須改變習慣的另一個方面但是可以運用顯式轉換
char chSomeChar = (char)
int nSomeInt = (int)A
在C中仍然存在著轉義符(字符含義)要換換腦筋請看表
table 轉義符( Escape Sequences)
轉義符 字符名
\ 單引號
\ 雙引號
\\ 反斜槓
\ 空字符
\a 感歎號(Alert )
\b 退格
\f 換頁
\n 新行
\r 回車
\t 水平 tab
\v 垂直tab
浮點型
兩種數據類型被當作浮點型float和double它們的差別在於取值范圍和精度
float 取值范圍在 x^~ x^之間 精度為位數
double 取值范圍在 x^ ~ x^之間 精度為 ~ 位數
當用兩種浮點型執行運算時可以產生以下的值
正零和負零
正無窮和負無窮
非數字值(NotaNumber縮寫NaN)
非零值的有限數集
另一個運算規則為當表達式中的一個值是浮點型時所有其它的類型都要被轉換成浮點型才能執行運算
小數型(The decimal Type)
小數型是一種高精度位數據類型它打算用於金融和貨幣的計算它所表示的范圍從大約x^ 到 x^具有至位有效數字要注意精度是以位數 (digits)而不是以小數位(decimal places)表示運算准確到個小數位的最大值
正如你所看到的它的取值范圍比double的還窄但它更精確因此沒有decimal和double之間的隱式轉換——往一個方向轉換可能會溢出往另外一個方向可能會丟失精度你不得不運用顯式轉換
當定義一個變量並賦值給它時使用 m 後綴以表明它是一個小數型
decimal decMyValue = m
如果省略了m在變量被賦值之前它將被編譯器認作double型
結構類型
一個結構類型可以聲明構造函數常數字段方法屬性索引操作符和嵌套類型盡管列出來的功能看起來象一個成熟的類但在C#中結構和類的區別在於結構是一個值類型而類是一個引用類型與C++相比這裡可以用結構關鍵字定義一個類
使用結構的主要思想是用於創建小型的對象如Point和FileInfo等等你可以節省內存因為沒有如類對象所需的那樣有額外的引用產生例如當聲明含有成千上萬個對象的數組時這會引起極大的差異
清單 包含一個命名為IP的簡單結構它表示一個使用byte類型的個字段的IP地址我不包括方法等因為這些工作正如使用類一樣將在下一章有詳細的描述
清單 定義一個簡單的結構
using System
struct IP
{
public byte bbbb
}
class Test
{
public static void Main()
{
IP myIP
myIPb =
myIPb =
myIPb =
myIPb =
ConsoleWrite({}{}myIPbmyIPb)
ConsoleWrite({}{}myIPbmyIPb)
}
}
枚舉類型
當你想聲明一個由一指定常量集合組成的獨特類型時枚舉類型正是你要尋覓的最簡單的形式它看起來可能象這樣
enum MonthNames { January February March April }
因我慣用缺省設置故枚舉元素是int型且第一個元素為值每一個連續的元素按遞增如果你想給第一個元素直接賦值可以如下把它設成
enum MonthNames { January= February March April }
如果你想賦任意值給每個元素——甚至相同的值——這也沒有問題
enum MonthNames { January= February= March= April= }
最後的選擇是不同於int的數據類型可以在一條語句中按如此賦值
enum MonthNames byte { January= February= March= April= }
你可以使用的類型僅限於longintshort和byte
引用類型
和值類型相比引用類型不存儲它們所代表的實際數據但它們存儲實際數據的引用在C#中提供以下引用類型給你使用
對象類型
類類 型
接口
代表元
字符串類型
數組
對象類型
對象類型是所有類型之母——它是其它類型最根本的基類因為它是所有對象的基類所以可把任何類型的值賦給它例如一個整型
object theObj =
給所有的C++程序員一個警告object並不等價於你可能正在尋找的void*無論如何忘掉指針總是個好主意
當一個值類型被加框(作為一個對象利用)時對象類型就被使用了這一章稍後會討論到加框和消框
類類型
一個類類型可以包含數據成員函數成員和嵌套類型數據成員是常量字段和事件函數成員包括方法屬性索引操作符構造函數和析構函數類和結構的功能是非常相似的但正如前面所述結構是值類型而類是引用類型
和C++相比僅允許單繼承(你不能擁有派生一個新對象的多重基類) 但是C#中的一個類可以派生自多重接口該接口在下一節將得到描述
第五章 類專門討論使用類編程這一節僅打算給出C#類在哪裡適合類型圖的一個全貌
接口
一個接口聲明一個只有抽象成員的引用類型跟C++中相似的概念為一個結構的成員且方法等於如果你不知道那些概念的任何東西這裡就是在C#中一個接口實際所做的僅僅只存在著方法標志但根本就沒有執行代碼這就暗示了不能實例化一個接口只能實例化一個派生自該接口的對象
可以在一個接口中定義方法屬性和索引所以對比一個類接口有什麼特殊性呢?當定義一個類時可以派生自多重接口而你只能可以從僅有的一個類派生
你可能會問OK但我必須實現所有的接口成員那麼我能從這個途徑得到什麼呢? 我想舉一個來自NET的例子
很多類實現了IDictionary 接口你可以使用簡單的類型轉換訪問接口
IDictionary myDict = (IDictionary)someobjectthatsupportsit
現在你的代碼可以訪問字典了可等等我說很多類可以實現這個接口——所以你可以在多個地方重用代碼來訪問IDictionary 接口!一旦學會任何地方都可使用
當你決定在類設計中使用接口時學習更多關於面向對象的設計是個好主意這本書不能教你這些概念但你可以學習如何創建接口以下的代碼段定義接口IFace它只有一個方法
interface IFace
{
void ShowMyFace()
}
正如我所提到的不能從這個定義實例化一個對象但可以從它派生一個類因此該類必須實現ShowMyFace抽象方法
class CFaceIFace
{
public void ShowMyFace()
{
ConsoleWriteLine(implementation)
}
}
接口成員和類成員的區別在於接口成員不能被實現因此我不想在下一章中再次提到這一點
代表元
一個代表元封裝了具有一些標志的一個方法基本上代表元是類型安全和函數指針的安全版本(回調功能)可以同時在一個代表元實例中同時封裝靜態和實例方法
盡管你可以用代表員當作具有方法但它們的主要用途是擁有有一個類事件再次我想把你引到下一章那裡會詳細地討論類
字符串類型
C程序員可能會詫異但當然C#有一個用於操作字符串數據的基本字符串類型字符串類直接派生自對象且它是被密封的這意味著再不能從它派生類就象其它類型字符串是預定義類System String的一個別名
它的用法十分簡單
string myString = some text
合並字符串同樣簡單
string myString = some text + and a bit more
而如果你想訪問單個字符所要做的就是訪問下標
char chFirst = myString[]
當比較兩個字符串是否相等時簡單地使用==比較操作符
if (myString == yourString) ……
我只不過想提到盡管字符串是一個引用類型比較時是比較值而不是比較引用(內存地址)字符串類型幾乎用於這本書的每一個例子中而且在這些例程中我會介紹給你一些由字符串對象所顯露的極其有趣的方法
數組
一個數組包含有通過計算下標訪問的變量所有包含於數組中且被當作元素的變量必須是同一類型這種類型自然被稱為數組類型數組可以存儲整數對象字符串對象或者 你提出的任何對象
數組的維數就是所謂的排(rank)它決定了相關數組元素的下標數最常用的數組是一維數組(第一排)一個多維數組具有的排數大於 每個維的下標始於終於維的長度減
應有足夠的理論支持讓我們看一下用一個數組初始化器( array initializer)初始化的數組
string[] arrLanguages = { C C++ C# }
該簡寫效果等同以下
arrLanguages[]=C arrLanguages[]=C++ arrLanguages[]=C#
而編譯器為你做了所有的工作當然它將同樣為多維數組初始化器工作
int[] arr = {{} {} {}}
它是以下的簡寫
arr[] = arr[] =
arr[] = arr[] =
arr[] = arr[] =
如果你不想事先初始化一個數組但知道了它的大小該聲明就象這樣
int[] myArr = new int[]
如果數組的大小必須動態地被計算用於數組創建的語句可以象這樣寫
int nVar =
int[] arrToo = new int[nVar]
正如我在這一節開始所陳述的你可以往數組裡面塞任何東西只要所有的元素類型都相同因此如果你想把任何東西放進一個數組就聲明它的類型為對象
加框和消框
這一章的課程中我已經給出了各式各樣的值類型和引用類型由於速度的原因你會使用值類型——它除了占據一定空間的內存塊外就沒有什麼了但是有時對象的方便性就象值類型一樣好用
這就是加框和消框登上了舞台的地方加框和消框是C#類型系統的核心概念通過允許一個值類型轉換成類型對象或從類型對象轉換成值類型這種機制形成了值類型和引用類型之間的捆綁連接任何東西終究是一個對象——但是僅當需要它們是對象時
加框轉換
給一個值加框指隱式地把任何值類型轉換成類型對象當一個值類型被加框時一個對象實例就被分配且值類型的值被拷貝給新的對象看以下例子
int nFunny =
object oFunny = nFunny
第二行的賦值暗示調用一個加框操作nFunny整型變量的值被拷貝給oFunny對象現在整型變量和對象變量都同時存在於棧中但對象的值居留在堆中那麼它暗示著什麼呢?它們的值互相獨立——在它們之間沒有連接(oFunny沒有引用nFunny的值) 以下代碼說明了結果
int nFunny =
object oFunny = nFunny
oFunny =
ConsoleWriteLine({} {} nFunny oFunny)
當代碼改變oFunny的值時nFunny的值並沒有改變只要你腦袋中有這個copy動作就能夠使用值類型的對象功能發揮出你的巨大優勢!
消框轉換
和加框相比消框是顯式操作——必須告訴編譯器你想從對象中抽取出哪一種值類型當執行消框操作時C#檢測所請求的值類型實際上存儲在對象實例中經過成功的校驗該值被消框
這就是消框如何執行
int nFunny =
object oFunny = nFunny
int nNotSoFunny = (int)oFunny
如果錯誤地請求一個double值
double nNotSoFunny = (double)oFunny
通用語言運行時(Common Language Runtime簡寫CLR)將會引發一個InvalidCastException異常你可以在第章 異常處理 中學到更多有關異常處理的知識
小結
在這一章中你學到了C#中用到的各種類型簡單的值類型包括整型布爾型浮點型和小數型你會非常經常地用到一些類型進行數學和金融的計算還有邏輯表達
在介紹引用類型之前我顯示了一個看起來象類的結構類型它幾乎如一個類般地運作但它只是一個值類型這使它更加適合需要有大量的小對象的場合引用類型起始於所有對象之母的objedt本身object是C#中所有對象的基類且它同樣用於值類型的加框和消框除此之外我還讓你領略了代表元字符串和數組
令C#程序員十分神氣的類型就是類它是C#面向對象編程的心髒下一章整章專門讓你迅速理解這個激動人心且功能強大的類型
From:http://tw.wingwit.com/Article/program/net/201311/11342.html