C#語言基礎篇
一、型別轉換
在 C# 中,變數分為以下幾種型別:
- 值型別(Value types)
- 引用型別(Reference types)
- 指標型別(Pointer types)
1.值型別變數可以直接分配給一個值。它們是從類 System.ValueType 中派生的。值型別直接包含資料。比如 int、char、float,它們分別儲存數字、字元、浮點數。當您宣告一個 int 型別時,系統分配記憶體來儲存值。
2.引用型別不包含儲存在變數中的實際資料,但它們包含對變數的引用,指的是一個記憶體位置。內建的
1> 物件(Object)型別 是 C# 通用型別系統(Common Type System - CTS)中所有資料型別的終極基類。Object 是 System.Object 類的別名。所以物件(Object)型別可以被分配任何其他型別(值型別、引用型別、預定義型別或使用者自定義型別)的值。但是,在分配值之前,需要先進行型別轉換。當一個值型別轉換為物件型別時,則被稱為 裝箱;另一方面,當一個物件型別轉換為值型別時,則被稱為 拆箱。(這個在前面的文章有提到過)
2> 可以儲存任何型別的值在動態資料型別變數中。這些變數的型別檢查是在執行時發生的。eg:dynamic a = 100;
3> 字串(String)型別 允許您給變數分配任何字串值。字串(String)型別是 System.String 類的別名。它是從物件(Object)型別派生的。字串(String)型別的值可以通過兩種形式進行分配:引號和 @引號。
C# string 字串的前面可以加 @(稱作"逐字字串")將轉義字元(\)當作普通字元對待,比如:
string str = @"C:\Windows"; 等價於 string str = "C:\\Windows";
String和string的區別:
1> string 是 C# 中的類,String 是 .net Framework 的類;(C# string 對映為 .net Framework 的String 如果用 string, 編譯器會把它編譯成 String,所以如果直接用 String 就可以讓編譯器少做一點點工作。)
2> string 是關鍵字,String 不是,也就是說 string 不能作為類、結構、列舉、欄位、變數、方法、屬性的名稱,而 String 可以。String 是 CLR 的型別名稱,而 string 是 C# 中的關鍵字。
3> String 只有在前面有 using System 的時候並且當前名稱空間中沒有名為 String 的型別(class、struct、delegate、enum)的時候才代表 System.String。
4>string 在編譯時候 C# 編譯器會預設將其轉換為 String,在這裡會多增加幾行轉換的程式碼。很多時候都是建議使用 CLR 的型別而不要使用 C# 的型別。
3.指標型別變數儲存另一種型別的記憶體地址。C# 中的指標與 C 或 C++ 中的指標有相同的功能。eg: int* iptr;
注:變數的隱式型別轉換zhin只能從低精度到高精度,所以,當一個精度高的資料型別與一個精度低的資料型別進行運算時,定義運算結果的變數型別必須與精度最高的變數型別相同。這是為了防止在運算過程中造成資料丟失。否則會出現類似的報錯:無法將型別‘double’隱式轉換為‘int’。
-
Convert.ToInt32() 與 int.Parse() 的區別:
1>Convert.ToInt32(a),int.Parse(a),但是如果a這個引數不存在,那麼前者將返回0,而用後一種辦法的話沒有a這個引數會會丟擲異常,我們可以捕獲異常然後再做相應的處理,比如提示使用者缺少引數,而不是把引數值當做0來處理;
2>對資料的四捨五入有區別:Convert.ToInt32(double value); 如果 value 為兩個整數中間的數字,則返回二者中的偶數;即 3.5轉換為4,4.5 轉換為 4,而 5.5 轉換為 6。 不過4.6可以轉換為5,4.4轉換為4;int.Parse(4.5),結果是4,沒有四捨五入。
3>int.Parse 是轉換 String為int;Convert.ToInt32是轉換繼承自Object的物件為int的(可以有很多其它型別的資料)。
const和readonly區別:
const,在編譯時就確定了值,必須在宣告時就進行初始化且之後不能進行更改,可在類和方法中定義。readonly,在執行時確定值,只能在宣告時或建構函式中初始化,只能在類中定義。
二、封裝
- public:所有物件都可以訪問;
- private:物件本身在物件內部可以訪問;
- protected:只有該類物件及其子類物件可以訪問
- internal:同一個程式集的物件可以訪問;
- protected internal:訪問限於當前程式集或派生自包含類的型別。
引數傳遞:
C# 中,有三種向方法傳遞引數的方式:
值引數 | 這種方式複製引數的實際值給函式的形式引數,實參和形參使用的是兩個不同記憶體中的值。在這種情況下,當形參的值發生改變時,不會影響實參的值,從而保證了實引數據的安全。 |
引用引數 | 這種方式複製引數的記憶體位置的引用給形式引數。這意味著,當形參的值發生改變時,同時也改變實參的值。形參和呼叫時的實參都需要加ref修飾。 |
輸出引數 | 這種方式可以返回多個值。形參和呼叫時的實參都需要加out修飾。 out型資料在方法中必須要賦值,否則編譯器會報錯。 |
三、結構體
- 結構可帶有方法、欄位、索引、屬性、運算子方法和事件。
- 結構可定義建構函式,但不能定義解構函式。但是,您不能為結構定義預設的建構函式。預設的建構函式是自動定義的,且不能被改變。
- 與類不同,結構不能繼承其他的結構或類。
- 結構不能作為其他結構或類的基礎結構。
- 結構可實現一個或多個介面。
- 結構成員不能指定為 abstract、virtual 或 protected。
- 當您使用 New 操作符建立一個結構物件時,會呼叫適當的建構函式來建立結構。與類不同,結構可以不使用 New 操作符即可被例項化。
- 如果不使用 New 操作符,只有在所有的欄位都被初始化之後,欄位才被賦值,物件才被使用。
- 類是引用型別,結構是值型別。
- 結構體中宣告的欄位無法賦予初值,類可以。
- 結構體中的建構函式必須對所有欄位賦予初值,類可以不。
- 類的物件是儲存在堆空間中,結構儲存在棧中。堆空間大,但訪問速度較慢,棧空間小,訪問速度相對更快。故而,當我們描述一個輕量級物件的時候,結構可提高效率,成本更低。當然,這也得從需求出發,假如我們在傳值的時候希望傳遞的是物件的引用地址而不是物件的拷貝,就應該使用類了。當堆疊的空間很有限,且有大量的邏輯物件時,建立類要比建立結構好一些;對於點、矩形和顏色這樣的輕量物件,假如要宣告一個含有許多個顏色物件的陣列,則CLR需要為每個物件分配記憶體,在這種情況下,使用結構的成本較低;在表現抽象和多級別的物件層次時,類是最好的選擇,因為結構不支援繼承。
四、靜態
可以使用 static 關鍵字把類成員定義為靜態的。當我們宣告一個類成員為靜態時,意味著無論有多少個類的物件被建立,只會有一個該靜態成員的副本。關鍵字 static 意味著類中只有一個該成員的例項。靜態變數用於定義常量,因為它們的值可以通過直接呼叫類而不需要建立類的例項來獲取。靜態變數可在成員函式或類的定義外部進行初始化。你也可以在類的定義內部初始化靜態變數。
五、繼承
C#不支援多重繼承,但是可以通過介面實現。
override是重寫,即將基類的方法在派生類裡直接抹去重新寫,故而呼叫的方法就是子類方法;而new只是將基類的方法在派生類裡隱藏起來,故而呼叫的仍舊是基類方法。
六、多型
"一個介面,多個功能"。在靜態多型性中,函式的響應是在編譯時發生的。在動態多型性中,函式的響應是在執行時發生的。
靜態多型性: C# 提供了兩種技術來實現,分別為:函式過載;運算子過載。
動態多型性:C# 通過抽象類和虛方法實現。
用關鍵字 abstract 建立抽象類,用於提供介面的部分類的實現。當一個派生類繼承自該抽象類時,實現即完成。抽象類包含抽象方法,抽象方法可被派生類實現。派生類具有更專業的功能。
抽象類的一些規則:
- 您不能建立一個抽象類的例項。
- 您不能在一個抽象類外部宣告一個抽象方法。
- 通過在類定義前面放置關鍵字 sealed,可以將類宣告為密封類。當一個類被宣告為 sealed 時,它不能被繼承。抽象類不能被宣告為 sealed。
virtual和abstract的區別:
- virtual修飾的方法必須有實現(哪怕是僅僅新增一對大括號),而abstract修飾的方法一定不能實現。
- virtual可以被子類重寫,而abstract必須被子類重寫。
- 如果類成員被abstract修飾,則該類前必須新增abstract,因為只有抽象類才可以有抽象方法。
- 無法建立abstract類的例項,只能被繼承無法例項化。
七、介面
介面定義了語法合同 "是什麼" 部分,派生類定義了語法合同 "怎麼做" 部分。介面定義了屬性、方法和事件,這些都是介面的成員。介面只包含了成員的宣告。成員的定義是派生類的責任。介面提供了派生類應遵循的標準結構。
1.通過介面可以實現多重繼承,C# 介面的成員不能有 public、protected、internal、private 等修飾符。原因很簡單,接口裡面的方法都需要由外面介面實現去實現方法體,那麼其修飾符必然是 public。
2.C# 介面中的成員預設是 public 的。當一個介面實現一個介面,這2個介面中有相同的方法時,可用 new 關鍵字隱藏父介面中的方法。
3.介面一旦被實現,實現類必須實現介面中的所有成員,除非實現類本身是抽象類。
介面和抽象類的區別:
1.介面用於規範,抽象類用於共性。抽象類是類,所以只能被單繼承,但是介面卻可以一次實現多個。
2.介面中只能宣告方法,屬性,事件,索引器。而抽象類中可以有方法的實現,也可以定義非靜態的類變數。
3.抽象類的例項是它的子類給出的。介面的例項是實現介面的類給出的。
4.在抽象類中加入一個方法,那麼它的子類就同時有了這個方法。而在介面中加入新的方法,那麼實現它的類就要重新編寫。
5.介面成員被定義為公共的,但抽象類的成員也可以是私有的、受保護的、內部的或受保護的內部成員。
持續更新中。。。後續有需要注意的會新增。
參考:http://www.runoob.com/csharp/csharp-polymorphism.html
這個系列的C#教程不錯,推薦大家看看,認真看完你的C#語言會上一個層次。