2.1 C#程序結構
•1.標識符
•2.關鍵字
•3.語句
•4.註釋
•5.命名空間
•6.類的定義和類的成員
•7.C#程序中的方法
•1.標識符
•C#中標識符的命名約定
–類名約定首字母大寫
–變量名、方法名等則約定使用Camel命名法。
2.關鍵字
•關鍵字(keyword)是C#程序語言保留作爲專用的有特定意義的字符串,不能作爲通常的標識符來使用。
•在C#語言中主要有如下關鍵字:abstract、as、base、bool、break、byte、case、catch、char、checked、、
class、const、continue、decimal、default
delegate、do、double、else、enum、event、explicit、extern、false、finally、fixed、float、for、foreach、get、goto、if、implicit、in、int、interface、internal、is、lock、long、namespace、new、null、object、operator、out、override、params、private、protected、public、readonly、ref、return、sbyte、sealed、set、short、sizeof、stackalloc、static、string、struct、switch、this、throw、true、try、typeof、uint、ulong、unchecked、unsafe、using、value、virtual、volatile、while。
3.語句
•語句是應用程序中執行操作的一條命令。C#代碼由一系列語句組成,每條語句都必須以分號結束。可以在一行中書寫多條語句,也可以將一條語句書寫在多行上。
•使用“{}”來表示應用程序中的不同層次和代碼塊。
4.註釋
•(1)行註釋:使用行註釋標識符“//”,表示該標識符後的“一行”爲註釋部分。
•(2)塊註釋:塊註釋分別以“/*”和“*/”爲開始和結束標識符,在此中間的內容,均爲註釋的部分。
•(3)文檔註釋:在C#中,還可以用“///”符號來開頭。在一般情況下,編譯器也會忽略它們,但可以通過配置相關工具,在編譯項目時,提取註釋後面的文本,創建一個特殊格式的文本文件,該文件可用於創建文檔說明書。
5.命名空間
•命名空間有兩種:系統命名空間和用戶自定義命名空間。
•系統命名空間是一個邏輯的命名系統,用來組織龐大的系統類資源,讓開發者使用起來結構清晰、層次分明、使用簡單。
•同時,用戶也可以使用自定義的命名空間以解決應用程序中可能出現的名稱衝突。
6.類的定義和類的成員
•每一個C#應用程序都必須藉助於.NET Framework類庫實現,因此必須使用using關鍵字把.NET
Framework類庫相應的命名空間引入到應用程序的項目中來。
•C#的源代碼必須存放到類中,一個C#應用程序至少要包括一個自定義類。自定義類使用關鍵字class聲明,其名字是一個標識符。
•類的成員包括屬性、方法和事件,主要由方法構成。例如控制檯應用程序或Windows應用程序必須包含Main方法,Main方法是應用程序的入口。程序的運行時,從Main方法的第一條語句開始執行,直到執行完最後一條語句爲止。
7.C#程序中的方法
•C#應用程序中的方法一般包括方法頭部和方法體。
•方法頭部主要包括返回值類型、方法名、形式參數(簡稱“形參”)類型及名稱,若方法中包含多個形參,形參之間用逗號分隔。
•方法體使用一對“{}”括起來,通常包括聲明部分和執行部分。聲明部分用於定義變量,執行部分可以包含賦值運算、算法運算、方法調用等語句或語句塊。
2.2 基本數據類型
1.數值類型
•值類型
值類型的數據存儲在內存的堆棧中,可以提供快速訪問。如果變量是值類型的,這個變量包含實際數據,在一個獨立的內存區域保存自己的值;如果在代碼中修改其值,在內存中會保存修改後的值。
當值類型在方法體內被聲明時,它們都是被放置到棧上的。
值類型有時也會被放置到堆上,記住這條規則——值類型總是放在它們被聲明的地方。如果一個值類型數據在方法體外被聲明,且存在於一個引用類型中,那麼它將被堆總的引用類型所取代。
•引用類型
引用類型指向存儲在內存堆中的數據的指針或引用。與純粹的地址不同,引用總是指向一個對象,而且這個對象具有指定的類型,並且在堆上分配了存儲空間。
2.數值類型
數值類型可以分爲整數類型和實數類型。
1.整數類型
•C#中支持8種整數類型:sbyte、byte、short、ushort、int、uint、long、ulong。這8種類型通過其佔用存儲空間的大小以及是否有符號來存儲不同極值範圍的數據,根據實際應用的需要,選擇不同的整數類型。
•整數類型的相關說明如表2-2所示。
2.實數類型
•實數類型包括浮點型和小數型(decimal),浮點型又包括單精度浮點型(float)和雙精度浮點型(double)。
•浮點型數據一般用於表示一個有確定值的小數。計算機對浮點數的運算速度大大低於對整數的運算速度,數據的精度越高,對計算機的資源要求越高。因此,在精度要求不是很高的情況下,儘量使用單精度類型(佔用4個字節)。如果精度要求較高的情況,則可以使用雙精度類型(佔用8個字節)。
•因爲使用浮點型表示小數的最高精度只能夠達到16位,爲了滿足高精度的財務和金融計算領域的需要,C#提供了小數型(佔用12個字節)。
3.字符類型
•字符類型包括字符型(char)和字符串型(string)。字符包括數字字符、英文字母、表達式符號等,C#提供的字符類型按照國際上公認的標準,採用Unicode字符集。
•字符型是指單個字符,一個Unicode的標準字符長度爲16位,佔用2個字節。char是類System.Char的別名。
•字符串型是指多個字符,其佔用字節根據字符數量而定(允許不包含字符的空字符串)。string是類System.String的別名。
3. 變量與常量
1.變量
• 在程序運行過程中,其值可以改變的量稱爲變量。變量可以用來保存從外部或內部接收的數據,也可以保存在處理過程中產生的中間結果或最終結果。在C#中,每一個變量都必須具有變量名、存儲空間和取值等屬性。
1.變量的聲明
• 要使用變量,就必須聲明它們,即給變量指定一個名稱和一種類型。變量命名應遵循標識符的命名規則,如:必須以字母、下劃線等Unicode字符開頭,不能以數字開頭,不能包含空格。聲明瞭變量後,編譯器纔會申請一定大小的存儲空間,用來存放變量的值。
2.變量的賦值
在C#中,變量必須賦值後才能引用。爲變量賦值,一般使用等號“=”。例如:
•char ch1,ch2;
•ch1 = ‘O’;
ch2 = ‘K’;
•int a,b,c;
•a = b = c = 0;
3.變量的初始化
變量的初始化就是在定義變量的同時給變量賦初值,其一般形式爲:
數據類型
變量名1 = 初值1 [,變量名2 =
初值2,... ];
例如:float f1=1.25, f2=3.6, f3;
2.常量
在程序運行過程中,其值保持不變的量稱爲常量。常量類似於數學中的常數。常量可分爲直接常量和符號常量兩種形式。
1.直接常量
所謂直接常量,就是在程序中直接給出的數據值。在C#中,直接常量包括整型常量、浮點型常量、小數型常量、字符型常量、字符串常量和布爾型常量。
1.直接常量
•(1)整型常量。整型常量分爲有符號整型常量、無符號整型常量和長整型常量,有符號整型常量寫法與數學中的常數相同,直接書寫,無符號整型常量在書寫時添加u或U標誌,長整型常量在書寫時添加l或L標記。例如,3、3U、3L。
•(2)浮點型常量。浮點型常量分爲單精度浮點型常量和雙精度浮點型常量。單精度浮點型常量在書寫時添加f或F標記,雙精度浮點型常量添加d或D標記。例如,7f、7d。
•需要注意的是,以小數形式直接書寫而未加標記時,系統將自動解釋成雙精度浮點型常量。例如,9.0即爲雙精度浮點型常量。
•(3)小數型常量。在C#中,小數型常量的後面必須添加m或M標記,否則就會被解釋成標準的浮點型數據。
C#中的小數和數學中的小數是有區別的。例如,5.0M。
•(4)字符型常量。字符型常量是一個標準的Unicode字符,使用兩個單引號來標記。例如,’5’、’d’、’昱’
、’#’都是標準的字符型常量。
C#還允許使用一種特殊形式的字符型常量,即以反斜槓“\”開頭,後面跟字符的字符序列,這種字符型常量被稱爲轉義字符常量。該形式的常量可以表示控制字符或不可見字符,當然也可以表示可見字符。例如,’\n’表示換行符,
•(5)字符串常量。字符串常量表示若干個Unicode字符組成的字符序列,使用兩個雙引號來標記。例如,“5”、“abc”、“清華大學”都是字符串。
•(6)布爾型常量。布爾型常量只有兩個:一個是true
,表示邏輯真;另一個是false,表示邏輯假。
2.符號常量
•符號常量使用const關鍵字定義,格式爲:
• const類型名稱 常量名
= 常量表達式;
•“常量表達式”不能包含變量、函數等值會發生變化的內容,可以包含其他已定義常量。如果在程序中非常頻繁地使用某一常量,可以將其定義爲符號常量,例如:
• const double PI = 3.14159;
3.類型轉換
• 在程序處理數據的過程中,經常需要將一種數據類型轉化爲另一種數據類型。數據類型的轉換方式有兩種:隱式轉換和顯式轉換。
1.隱式轉換
•隱式轉換一般發生在數據進行混合運算的情況下,是由編譯系統自動進行的,不需要加以聲明。在該過程中,編譯器無需對轉換進行詳細檢查就能夠安全地執行轉換。隱式轉換一般不會失敗、不會出現致命隱患或造成信息丟失。例如:
•short s = 1;
int i = s;
•需要注意的是,隱式轉換無法完成由精度高的數據類型向精度低的類型轉換。例如:
•int i = 1;
short s = i;
//錯誤,如果必須進行轉換,就應該使用顯式類型轉換
2.顯式轉換
• 顯式類型轉換,又稱爲強制類型轉換,該方式需要用戶明確的指定轉換的目標類型,該類型轉換的一般形式爲:
(類型說明符)(需要轉換的表達式)
•例如:
•short s = 7;
int i = (int)s;
//將s的值顯式轉化爲int類型,並賦值於int類型變量i
顯式轉換包含所有的隱式類型轉換,即把任何編譯器允許的隱式類型轉換寫成顯式轉換都是合法的。顯式類型轉換並不一定總是成功,且轉換過程中會出現數據丟失。
3. 使用方法進行數據類型的轉換
•(1)Parse方法
• Parse方法可以將特定格式的字符串轉換爲數值,其使用格式爲:
• 數值類型名稱.Parse(字符串型表達式)
•例如:
•int i = int.Parse("100");
//字符串符合整型格式,轉換成功
•int j = int.Parse(“100.0”);//字符串不符合符合整型格式,出錯
•(2)Convert類的方法
•(3)ToString方法
4.引用類型
從數據存儲的角度,C#的類型可分爲值類型和引用類型。一個具有引用類型的數據並不駐留在棧內存中,而是存儲於堆內存中。在堆內存中分配內存空間直接存儲所包含的值,而在棧內存中存放定位到存儲具體值的索引位置編號。
當訪問一個具有引用類型的數據時,需要到棧內存中檢查變量的內容,而該內容指向堆中的一個實際數據。
C#的引用類型包括類、接口、委託、數組和字符串等
1.類
•類是C#面向對象程序設計中最重要的組成部分,是最基本的編程單位,它由若干個數據成員、方法成員等組成。C#中的類需要使用class關鍵字來進行表示和聲明,一個完整的類的定義示例如下:
class Student
{ int no;
string name;
char sex; int score;
public string Answer()
{
string result = "該考生信息如下:";
result += "\n學號:" + no;
result += "\n姓名:" + name;
return result;
}
}
2.接口
•接口是一種特殊的數據類型,接口與類的關係是:接口負責聲明類的標準行爲,而類負責實現這些行爲。使用接口來設計程序的最大好處是實現了軟件設計的規範化和標準化。
•在C#中,接口類型使用interface進行標識。一個完整的接口示例如下:
interfaceIStudent
//聲明接口
{
string Answer();
}
•注意,方法中不能夠包含任何語句。
3.委託
•委託(delegate)相當於C++中指向函數的指針,但與C++的指針不同,委託完全是面向對象的,它把一個對象實例和方法都進行封裝,所以委託是安全的。
•C#使用delegate來標記一個委託,其一般形式如下:
• delegate
返回值類型 委託名稱(方法參數列表)
•一個完整的委託示例如下:
• delegate void
MyDelegate();
//聲明委託
•其中,MyDelegate是委託的名稱,void表示該委託所指向的方法無返回結果,圓括號中沒有方法參數列表,表示該委託指向的方法不需要參數。
4.數組
•數組是指同類數據組成的集合,它是數據最常用的存儲方式之一。數組中包含的變量稱爲數組的元素,數組元素可以是包括數組類型在內的任何類型。
•C#支持的數組種類:
一維數組
規則的多維數組
不規則多維數組
• 數組能夠存儲整型、字符串等類型的數據,但是不論數組存儲了多少個數據,其中的數據必須是同一種類型。
•任何數組都是System.Array的派生類
•爲什麼不直接使用System.Array?
–System.Array是抽象類,不能實例化
–System.Array假定成員數據類型是object
•對於值類型,會增加box/unbox的開銷
•對於引用類型,使用時需顯式轉換
5.字符串
字符串是一個由若干個Unicode
字符組成的字符數組。字符串常量使用雙引號來標記,如“string 123”就是一個字符串常量。
String和String在c#中是一樣的,String類屬於System命名空間,是.NET
Framework提供的專門處理字符串的類庫,string是String在C#中的別名。
•靜態串string
String對象的內容是不可改變的,所以稱做靜態串。不可改變指的是隻要創建一個String類型的對象,就不能再更改對象的值,任何賦值、修改操作都將被分配一個新值。
string lastName;
lastName = "Ming";
string firstName = "Zhang";
string name = firstName + " " + lastName;
string sameName = name;
char[] s2 = { '計', '算', '機',
'科', '學' };
string s3 = new string(s2);
•可以使用String類的Compare、CompareOrdinal、CompareTo、Equals、EndsWith和StartsWith等方法進行字符串的比較。
•使用Copy和CopyTo方法可以將字符串或子字符串複製到另一個字符串或Char類型數組。
•使用IndexOf、IndexOfAny、LastIndexOf和LastIndexOfAny等方法可以獲取字符串中的字符串。
•使用Substring和Split方法可以通過原始字符串的組成部分創建一個或多個新字符串。
•使用Concat和Join方法可以通過一個或多個子字符串創建新字符串。
•使用Insert、Replace、Remove、PadLeft、PadRight、Trim、TrimEnd、和TrimStart等方法可以修改字符串的全部或部分。
•使用ToLower、ToLowerInvariant、ToUpper和ToUpperInvariant等方法可以更改字符串中Unicode字符的大小寫。
•使用Length屬性可以獲取字符串中Char對象的數量,使用Chars屬性可以訪問字符串中實際的Char對象。
•.NET Framework類庫中的System.Text.StringBuilder類用來構造可變字符串,包含Length、Append、Insert、Remove、Replace、ToString等成員,分別用來獲得字符串長度、追加字符、刪除字符、替換字符和將StringBuilder轉換成string等操作。
6.集合
•集合是通過高度結構化的方式存儲任意對象的類。集合不僅能隨意調整大小,而且對存儲或檢索存儲在其中的對象提供了更高級的方法。而數組的類型必須是相同的,且創建時就必須知道數組內含有多少元素,還需要通過循環索引來訪問這些元素。與數組相比,使用集合管理數據會更加方便。
• 實際上,數組是集合的一種類型。
1.集合類的選擇
• 每個集合有其自身的功能及限制,集合專用性越強,其限制就越多。選擇集合類時,一般要考慮以下問題:
•(1)是否需要隨機訪問集合中的元素。此時不能選擇Queue
隊列類、Stack棧類、LinkedList
雙向鏈表類,而其餘的集合可以提供隨機訪問。
•(2)是否需要一個序列列表。需要先進先出操作時,可使用
Queue 隊列類;而需要後進先出操作時,可使用
Stack棧類。
•(3)是否包含一個值,還是一個鍵和一個值的集合。其中,“一個值”的集合是一種基於IList列表接口派生的集合,“一個鍵和一個值”的集合是一種基於IDictionary字典接口的集合。
2.集合的使用
• C#爲用戶提供了foreach語句,更好地支持了集合的使用。利用foreach
語句可以方便地遍歷集合中的每一個元素,foreach
語句的表達式的類型必須是集合類型。
• foreach語句的格式爲:
foreach ( 類型 標識符
in 表達式 )
{ 嵌入語句;
}
• foreach語句的“類型”和“標識符”聲明該語句的迭代變量,迭代變量是一個其範圍覆蓋整個嵌入語句的只讀局部變量。在foreach語句執行期間,迭代變量表示當前正在爲其執行迭代的集合元素。
3.集合的創建與操作
經常使用的集合有ArrayList、Queue、Stack、Hashtable和SortedList,這些集合都位於System.Collections命名空間中,在使用時需要事先引用該命名空間。
(1)動態數組ArrayList。ArrayList的大小可根據需要自動擴充,允許在其中添加、插入或移除某一範圍的元素。ArrayList的下限始終爲零,且始終只是一維的。
• 創建動態數組對象的一般形式如下:
ArrayList
列表對象名 = new ArrayList( );
•
ArrayList和
Array的關係
•ArrayList和
Array 就像
StringBuilder和
String
–改固定容量爲容量可變
–容量變化的方式:新生成更大容量的對象
–潛在的內存拷貝,如:Insert、Remove、RemoveAt等操作,可能會引起內存拷貝。若成員是引用類型,則僅拷貝引用
•ArrayList常用的方法和功能包括:Add,向數組中添加一個元素;Remove,刪除數組中的一個元素;RemoveAt,刪除數組中指定索引處的元素;Reverse,反轉數組的元素;Sort,以從小到大的順序排列數組的元素;Clone,複製一個數組。
(2)隊列Queue:數據列表ArrayList的變種。
•隊列是一種先進先出的數據結構,當插入或刪除對象時,對象從隊列的一端插入,從另外一端移除。
•創建隊列對象的一般形式如下:
Queue
隊列名 = new Queue([隊列長度][,增長因子]);
說明:隊列長度默認爲32,增長因子默認爲2.0。即每當隊列容量不足時,隊列長度調整爲原來的2倍。
•隊列包括Enqueue、Dequeue、Peek、Clear和Contains等方法,主要功能分別是添加隊尾數據、移除並返回隊頭數據、返回隊頭數據、清空隊列和檢查是否包含某個數據。其中,Enqueue和Dequeue每操作一次只能添加或刪除一個數據。
(3)棧Stack:數據列表ArrayList的變種。
• 棧是一種先進後出的數據結構,這種數據結構在插入或刪除對象時,只能在棧頂插入或刪除。
• 創建棧對象的一般形式如下:
Stack棧名
= new Stack( );
棧包括Push、Pop、Peek、Clear和Contain等方法,分別可以實現棧頂數據推進、棧頂數據彈出、返回棧頂數據、清空棧和檢查棧中是否包含某個數據的操作。其中,Push和Pop每操作一次只能添加或刪除一個數據。
(4)有序列表SortedList。
•列表中每個元素,對應一個key。
• SorterList類表示“鍵/值對”的集合,這些鍵和值按鍵排序並可按照鍵和索引訪問。SortedList最合適對一列健/值對進行排序,在排序時,是對鍵進行排序。
• SortedList是Hashtable和Array的混合。當使用Item索引器屬性按照元素的鍵訪問元素時,其行爲類似於Hashtable。當使用GetByIndex或SetByIndex方法按照元素的索引訪問元素時,其行爲類似於Array。
(5)哈希表Hashtable。
• 哈希表又稱散列表,表示鍵/值對的集合。哈希表在保存集合元素時,首先要根據鍵自動計算哈希代碼,以確定該元素的保存位置,再把元素的值放入相應位置所指向的存儲桶中。查找時,再次通過鍵所對應的哈希代碼到特定存儲桶中搜索,這樣可以極大的提高查找一個元素的效率。
• 創建哈希表對象的一般形式如下:
Hashtable哈希表名
= new Hashtable([哈希表長度][,增長因子]);
• 說明:哈希表默認長度爲0,默認增長因子爲1.0。
• 哈希表包括Add、Remove、Clear和Contains等方法,可以實現對哈希表數據的添加、移除、清空和查詢。
5.值類型
引用類型用於存儲對實際數據的引用,而值類型用於存儲數據的值。值類型可以進一步劃分爲簡單類型、枚舉類型和結構類型,而簡單類型包括前面介紹的整型、實數型、字符型和布爾型。
1.枚舉
1.枚舉類型的定義和使用
•枚舉實際上是爲一組在邏輯上密不可分的整數值提供便於記憶的符號,是一些取了名字的常量集合。
•例如: //
定義一個表示星期的枚舉類型WeekDay
enumWeekDay {
Sunday,Monday,Tuesday,Wednesday,
Thursday,Friday,Saturday };
WeekDay day;
// 聲明一個WeekDay枚舉類型的變量day
•枚舉類型定義好後,就可以用來聲明變量。枚舉類型的變量在某一時刻只能取枚舉中某一個元素的值,如day的值要麼是Sunday要麼是Monday或其他的元素,但它在一個時刻只能代表具體的某一天,也不能是枚舉集合以外的其他元素。
2.結構
結構類型是一種可以自己定義的數據類型,是一種可以包含不同類型數據成員的數據結構。在結構類型中可以聲明多個不同數據類型的組成部分,這些組成部分被稱爲結構體的成員。結構體允許嵌套。
1.結構類型的定義
結構類型必須使用struct來標記。結構類型包含的成員類型沒有限制,任何合法的成員都可以包含在一個結構體內。其中,數據成員表示結構的數據項,方法成員表示數據項的操作。
1.結構類型的定義
C#內置的結構類型主要有DateTime和TimeSpan。
DateTime表示某個時間點,其成員主要包括Year、Month、Day、Hour、Minute、Second、Today、Now等,分別代表年、月、日、時、分、秒、今天和現在時間。
TimeSpan代表某個時間段,其成員主要有Days、Hours、Minutes、Seconds,分表示整天數、整時數、整分數和整秒數。
3.裝箱與拆箱
•在C#的程序設計中,值類型可以通過隱式或顯式轉換方法進行數據類型轉換。對於引用類型,則可以將任何類型轉換爲對象,或將任何類型的對象轉換爲與之類型兼容的數據類型。
• C#把任何值類型轉換爲對象的操作稱爲裝箱,而把對象轉換爲與之類型兼容的值類型的操作稱爲拆箱。
1.裝箱
• 裝箱是指將一個值類型變量轉換爲一個引用類型的變量。裝箱的過程是:首先創建一個引用類型的實例,然後將值類型變量的內容複製給該引用類型實例。
1.裝箱
• 在.NET中,Object類是所有類型的基類。所以,裝箱意味着把一個值類型的數據轉換爲一個對象(object)類型的數據。
• 裝箱過程是隱式轉換過程,由系統自動完成,一般在賦值運算前完成。例如:
inti = 123;
object boxing = i;
• 上述代碼運行時,先聲明一個Object對象boxing,然後系統臨時創建一個沒有名字的Object對象,將整型變量i的值複製給它,再賦值給Object對象boxing。
2.拆箱
• 拆箱與裝箱在邏輯上是一對互逆的過程。拆箱是指將一個引用類型顯式地轉換成一個值類型。需要指出的是,裝箱操作可以隱式進行,但拆箱操作必須是顯式的。
• 拆箱過程分成兩步:首先,檢查這個對象實例,看它是否爲給定的值類型的裝箱值;然後,把這個實例的值複製給相應值類型的變量。例如:
intval = 100;
object boxing =
val; //
裝箱
inti = (int)boxing +100;
// 拆箱
• 拆箱意味着把一個對象類型數據轉換爲一個值類型數據,拆箱過程必須是顯式轉換過程。拆箱時先檢查對象所引用的數據的類型,確保拆箱前後的數據類型相同,再複製出一個值類型數據。