- 21天學通C#
- 秦婧等編著
- 3517字
- 2018-12-29 13:23:24
2.1 認識數據類型
C#在對數據進行操作之前,必須指定其屬于什么類型。C#基本上完全保留了C++中的所有數據類型。除了指針以外,同時還吸收了Visual Basic和Java中的一些數據類型。關于C#的數據類型關系,如圖2.1所示。

圖2.1 C#的數據類型
警告:C#同樣支持指針類型,但是只能在“不安全代碼”中才可以直接使用指針類型,其他地方幾乎不能使用。
2.1.1 值類型
所謂值類型,就是一種由類型的實際值表示的數據類型。例如可以把數字“3”看做是整數型,而把3.00看做是小數型一樣。在計算機程序里,通常把小數型叫做浮點型,浮點的意思可以理解為小數點的位置不固定。C#的值類型可以分為簡單類型、枚舉類型和結構類型。下面就結合實例來分別介紹這些值類型。
簡單類型包含整數類型、字符類型、實數類型、布爾類型。小數類型包含在了實數類型中,小數點后面必須是十進制的數。顧名思義,整數類型變量的值為整數,數學上的整數可以從負無窮大到正無窮大。但是由于計算機的存儲單元是有限的,所以計算機語言提供的整數類型值總是在一定的范圍之內,C#中有9種整數類型,即int、uint、long、ulong、char、short、ushort、sbyte、byte,它們占用的空間和取值范圍如表2.1所示。
注意:每種值類型都有一個隱式的構造函數,這個構造函數可以理解為值類型本身為自己服務的一種功能,用來初始化類型的默認值。
表2.1 C#值類型數據的占用字節數和范圍

【范例2-1】整數類型的定義和運算。本例中定義了兩個班級變量,并計算兩個班級人數的總和,如示例代碼2-1所示。
示例代碼2-1
01 using System; //包含基本類和基類 02 …… //還有其他命名空間,也是系統生成的,在此省略 03 namespace Ex_2_1 //程序的命名空間,也是項目名稱,如Ex_2_1 04 { 05 class Program 06 { 07 static void Main(string[] args) //主函數,也是入口函數 08 { 09 int a = 50; //定義a班,有50個同學 10 int b = 40; //定義b班,有40個同學 11 Console.WriteLine(a+b); //輸出總人數 12 Console.ReadLine(); //加上這行才能看到運行結果,否則一閃而過 13 } 14 } 15 }
【運行結果】選擇“調試”|“啟動調試”選項運行程序,結果如圖2.2所示。

圖2.2 整數實例運算結果
【代碼解析】在本例中,首先定義了兩個int類型的變量a和b。在此處,它們分別代表a班的人數和b班的人數,在實際的開發過程中,也可以表示具有整數類型的量。分別給a、b賦值為50和40,然后在第11行處輸出a班和b班人數的總和。
提示:Console.WriteLine與Console.Write都可以輸出,兩者的區別在于Console.WriteLine輸出后換行,而Console.Write只是輸出。有的讀者可能在編譯的時候窗口一閃而過了,無法看到運行結果,在程序的最后加上Console.ReadLine()就能看見運行結果了。
計算機處理的信息除了數字以外,主要就是字符了。字符包括數字字符、英文字母、表達符號等。字符類型在C#中被看做是一種特殊的整數類型,它們都采用Unicode字符編碼。在使用字符常量時,必須用單引號引上常量的值。不包含任何字符的字符串,就稱為空字符串,例如:
char myname = ’Z’;
除了單個字符外,還有一串字符組成的字符串,在C#語言中,字符串通過關鍵字string來定義。例如定義一個字符串變量可以這樣:
string sName=”I Love C#”;
字符串在計算機里存儲,實際上是按單個字符的方式連續組成起來的,其實質就是字符數組。這里可以理解為一連串存儲在鄰近位置的字符,它的存儲方式如圖2.3所示。

圖2.3 I Love C#字符串的存儲形式
警告:其實,計算機在為每個字符串分配空間時,都會在其后加上一個轉義字符“\0”,用于表示字符串的結束。這樣,人們用肉眼看時,看到的字符串長度比實際上的要小1。
2.1.2 引用類型
引用類型又稱為對象。引用類型的變量是不直接存儲變量值的,它是指向要存儲的值,實際上就是存儲數據引用值的地址。class、interface、delegate可以用于聲明引用類型。C#的引用類型有4種,即類、代表、數組、接口。
特別要注意區別值類型和引用類型。值類型在內存中存放的是變量的值。而引用類型在內存中存放的是變量所指向的地址。它沒有真正存在的值,是引用別的值。這個過程類似于生活中的代理產品一樣,代理商就像引用類型,其沒有自己的產品,而是代理廠家的產品,使其就像是自己的產品一樣。
警告:引用類型存儲的實際是引用值的地址,初學者常把它和其他數據類型一同理解。它是沒有實際值的。
【范例2-2】下面演示引用類型的使用方法。用一個變量指向一個有實際內容的變量空間,并且輸出,如示例代碼2-2所示。
示例代碼2-2
01 using System; //包含基本類和基類 02 …… //還有其他命名空間,也是系統生成的,在此省略 03 namespace Ex_2_2 //程序的命名空間,也是項目名稱,如Ex_2_2 04 { 05 class Program 06 { 07 static void Main(string[] args) //主函數,也是入口函數 08 { 09 demo n1 = new demo(); //將引用類型demo實例化 10 n1.a = 10; //為成員a賦值 11 n1.b = 15; 12 demo n2 = n1; //只是賦值指針,將指針指向n1.a。注意這里是關鍵 13 Console.WriteLine(n2.a); //輸出結果,其值實際上還是ni存儲單元中的 14 Console.WriteLine(n2.b); //輸出結果,是ni中的成員b的值 15 Console.Read(); //獲取輸入焦點,為了看運行結果 16 } 17 class demo //引用類型的聲明 18 { 19 public int a; //成員變量 20 public int b; //成員變量 21 } 22 } 23 }
【運行結果】選擇“調試”|“啟動調試”選項運行程序,結果如圖2.4所示。

圖2.4 引用類型
【代碼解析】在本例中演示了引用類型的使用。在第17行代碼處用class聲明了引用類型,并在第19行和第20行代碼處定義了兩個成員變量。就相當于給這個引用類型定義了兩個性質一樣,如定義了人的身高和體重。在第09行處實例化了demo對象,就像從人的概念中實實在在地創造了一個活生生的人。在第10行和第11行中為其成員賦值,類似于給人取了名,或者說這個人有了身高。值得注意的是,在第12行,用n2指向n1的指針,而不是為其賦值,這里是關鍵。
注意:引用類型只是將指針指向內存中的存儲單元。
2.1.3 創建和使用數組
數組是引用類型中的自描述類型,是指由同一種數據類型組成的集合。最常見的數組如矩陣數組,它包含了一維數組和多維數組。數組能夠存儲多種數據類型,但是在同一個數組中的數據必須都是同一種類型。定義數組時,可以在“[]”中定義元素的個數和數據,如int [] array=new [5]。使用數組的下標來獲取數組的元素。下標從0開始,一直到元素和個數減1。例如在上述的數組中,array[0]就是第一個元素。
【范例2-3】下面來演示一維數組的使用方法。本例中用for循環輸出5 個數字,這5個數字存在一個有5個元素的一維數組中,如示例代碼2-3所示。
示例代碼2-3
01 using System; //包含基本類和基類 02 …… //還有其他命名空間,也是系統生成的,在此省略 03 namespace Ex_2_3 //程序的命名空間,也是項目名稱,如Ex_2_3 04 { 05 class Program 06 { 07 static void Main(string[] args) //主函數,也是入口函數 08 { 09 int[] array = new int[5]; //定義一個一維數組,它有5個元素 10 for (int i = 0; i < array.Length; i++) //循環計算i的值,最大長度是數組的長度 //array.Length 11 { 12 array[i] = i + 10; //將i的值加上10再賦給第i個數組元素 13 Console.WriteLine(array[i]);//輸出第i個數組元素的值 14 } 15 Console.ReadLine(); //獲取輸入焦點,為了看運行結果,放在循環 //體之外 16 } 17 } 18 }
【運行結果】選擇“調試”|“啟動調試”選項運行程序,結果如圖2.5所示。

圖2.5 數組演示結果
【代碼解析】上述代碼首先定義了一個長度為5的int類型數組array。接著通過for循環實現將變量i的值循環賦值給數組的每一個元素。值得注意的是array.Length,它表示數組的長度。
注意:數組的下標是從0開始的,而不是從1開始。很多初學者對此很不理解,其實在計算機中,很多計數都是從0開始的,它就像人們生活中,數數是從1開始一樣。
值類型和引用類型這兩種類型存儲在內存的不同地方。值類型存儲在堆棧中,而引用類型存儲在托管堆上,這種存儲位置的不同對數據操作會有不同的影響。關于各個類型是如何相關聯的,如圖2.6所示。
2.1.4 類型轉換
類型轉換是相對數據類型而言的,就是不同數據類型之間的轉換。C#的數據類型轉換分為隱式轉換和顯式轉換。隱式轉換就是將低精度數值轉換為高精度數值,直接賦值而不用轉換。例如int i=100;double d=i;顯式轉換就是將高精度數值轉換為低精度數值,使用顯式轉換時,必須指明轉換目標類型。
C#數值類型包括byte、short、int、long、float、double等。按照這個排列的順序,各種類型可以依次向后自動進行轉換。例如,把一個int型的數據賦值給一個long型的變量,int值會自動轉換成long型值,然后再賦給long型變量。

圖2.6 各個類型的關聯關系
【范例2-4】下面來演示如何進行顯式轉換,它是從高精度轉換成低精度,如示例代碼2-4所示。
示例代碼2-4
01 using System; //包含基本類和基類 02 …… //還有其他命名空間,也是系統生成,在此省略 03 namespace Ex_2_4 //程序的命名空間,也是項目名稱,如Ex_2_4 04 { 05 class Program 06 { 07 static void Main(string[] args) //主函數,也是入口函數 08 { 09 double d = 100.5; //定義并初始化一個雙精度型變量d 10 int i; //定義了一個整數型,用于接收轉換后的值 11 i = (int)d; //進行顯式轉換,從double(雙精度)到int(低精度) 12 Console.WriteLine(i); //輸出結果 13 Console.ReadLine(); //獲取輸入焦點,為了看運行結果 14 } 15 } 16 }
【運行結果】選擇“調試”|“啟動調試”選項運行程序,結果如圖2.7所示。

圖2.7 顯式轉換運行結果
【代碼解析】上述代碼首先定義了double類型變量d,并賦值100.5。再定義了一個int型變量i用于接收轉換后的數據結果。接著通過(int)把double型轉換成int型,是從高精度轉向低精度。讀者可以從這個實例中體會顯式與隱式的區別。