c#基礎
1. C# 程序結構
一個 C# 程序主要包括以下部分:
- 命名空間聲明(Namespace declaration)
- 一個 class
- Class 方法
- Class 屬性
- 一個 Main 方法
- 語句(Statements)& 表達式(Expressions)
- 註釋
2. C# 基本語法
C# 是一種面向對象的編程語言。
在面向對象的程序設計方法中,程序由各種相互交互的對象組成。
相同種類的對象通常具有相同的類型,或者說,是在相同的 class 中。
例如,以 Rectangle(矩形)對象為例。
它具有 length 和 width 屬性。
根據設計,它可能需要接受這些屬性值、計算面積和顯示細節。
using 關鍵字
在任何 C# 程序中的第一條語句都是:
using System;
using 關鍵字用於在程序中包含命名空間。
一個程序可以包含多個 using 語句。
class 關鍵字
class 關鍵字用於聲明一個類。
成員變量
變量是類的屬性或數據成員,用於存儲數據。
成員函數
函數是一系列執行指定任務的語句。
類的成員函數是在類內聲明的。
標識符
標識符是用來識別類、變量、函數或任何其它用戶定義的項目。
在 C# 中,類的命名必須遵循如下基本規則:
- 標識符必須以字母、下劃線或 @ 開頭,後面可以跟一系列的字母、數字( 0 - 9 )、下劃線( _ )[email protected]
C# 關鍵字
關鍵字是 C# 編譯器預定義的保留字。
這些關鍵字不能用作標識符,但是,如果您想使用這些關鍵字作為標識符,可以在關鍵字前面加上 @ 字符作為前綴。
在 C# 中,有些標識符在代碼的上下文中有特殊的意義,如 get 和 set,這些被稱為上下文關鍵字(contextual keywords)。
3. C# 數據類型
在 C# 中,變量分為以下幾種類型:
- 值類型(Value types)
- 引用類型(Reference types)
- 指針類型(Pointer types)
值類型(Value types)
值類型變量可以直接分配給一個值。
它們是從類 System.ValueType 中派生的。
值類型直接包含數據。比如 int、char、float,它們分別存儲數字、字母、浮點數。
當您聲明一個 int 類型時,系統分配內存來存儲值。
如需得到一個類型或一個變量在特定平臺上的準確尺寸,可以使用 sizeof 方法。
表達式 sizeof(type) 產生以字節為單位存儲對象或類型的存儲尺寸。
引用類型(Reference types)
引用類型不包含存儲在變量中的實際數據,但它們包含對變量的引用。
換句話說,它們指的是一個內存位置。使用多個變量時,引用類型可以指向一個內存位置。如果內存位置的數據是由一個變量改變的,其他變量會自動反映這種值的變化。內置的 引用類型有:object、dynamic 和 string。
對象(Object)類型
對象(Object)類型 是 C# 通用類型系統(Common Type System - CTS)中所有數據類型的終極基類。Object 是 System.Object 類的別名。所以對象(Object)類型可以被分配任何其他類型(值類型、引用類型、預定義類型或用戶自定義類型)的值。但是,在分配值之前,需要先進行類型轉換。
當一個值類型轉換為對象類型時,則被稱為 裝箱;另一方面,當一個對象類型轉換為值類型時,則被稱為 拆箱。
object obj;
obj = 100; // 這是裝箱
動態(Dynamic)類型
您可以存儲任何類型的值在動態數據類型變量中。這些變量的類型檢查是在運行時發生的。
聲明動態類型的語法:
dynamic <variable_name> = value;
例如:
dynamic d = 20;
動態類型與對象類型相似,但是對象類型變量的類型檢查是在編譯時發生的,而動態類型變量的類型檢查是在運行時發生的。
字符串(String)類型
字符串(String)類型 允許您給變量分配任何字符串值。
字符串(String)類型是 System.String 類的別名。
它是從對象(Object)類型派生的。
字符串(String)類型的值可以通過兩種形式進行分配:引號和 @引號。
例如:
String str = "runoob.com";
一個 @引號字符串:
@"runoob.com";
C# string 字符串的前面可以加 @(稱作"逐字字符串")將轉義字符(\)當作普通字符對待,比如:
string str = @"C:\Windows";
等價於:
string str = "C:\\Windows";
@ 字符串中可以任意換行,換行符及縮進空格都計算在字符串長度之內。
string str = @"<script type=""text/javascript"">
<!--
-->
</script>";
用戶自定義引用類型有:class、interface 或 delegate。
我們將在以後的章節中討論這些類型。
指針類型(Pointer types)
指針類型變量存儲另一種類型的內存地址。
C# 中的指針與 C 或 C++ 中的指針有相同的功能。
聲明指針類型的語法:
type* identifier;
例如:
char* cptr;
int* iptr;
我們將在章節"不安全的代碼"中討論指針類型
4. C# 類型轉換
類型轉換從根本上說是類型鑄造,或者說是把數據從一種類型轉換為另一種類型。在 C# 中,類型鑄造有兩種形式:
- 隱式類型轉換 - 這些轉換是 C# 默認的以安全方式進行的轉換, 不會導致數據丟失。例如,從小的整數類型轉換為大的整數類型,從派生類轉換為基類。
- 顯式類型轉換 - 顯式類型轉換,即強制類型轉換。顯式轉換需要強制轉換運算符,而且強制轉換會造成數據丟失。
C# 類型轉換方法
5. C# 變量
一個變量只不過是一個供程序操作的存儲區的名字。
在 C# 中,每個變量都有一個特定的類型,類型決定了變量的內存大小和布局。
範圍內的值可以存儲在內存中,可以對變量進行一系列操作。
我們已經討論了各種數據類型。
C# 中提供的基本的值類型大致可以分為以下幾類:
類型 |
舉例 |
整數類型 |
sbyte、byte、short、ushort、int、uint、long、ulong 和 char |
浮點型 |
float 和 double |
十進制類型 |
decimal |
布爾類型 |
true 或 false 值,指定的值 |
空類型 |
可為空值的數據類型 |
C# 允許定義其他值類型的變量,比如 enum
也允許定義引用類型變量,比如 class。
接受來自用戶的值
System 命名空間中的 Console 類提供了一個函數 ReadLine(),用於接收來自用戶的輸入,並把它存儲到一個變量中。
例如:
int num;
num = Convert.ToInt32(Console.ReadLine());
函數 Convert.ToInt32() 把用戶輸入的數據轉換為 int 數據類型,因為 Console.ReadLine() 只接受字符串格式的數據。
6. C# 運算符
運算符是一種告訴編譯器執行特定的數學或邏輯操作的符號。C# 有豐富的內置運算符,分類如下:
- 算術運算符
- 關系運算符
- 邏輯運算符
- 位運算符
- 賦值運算符
- 其他運算符
7. 常量
字符串常量
字符常量是括在雙引號 "" 裏,或者是括在 @"" 裏。
字符串常量包含的字符與字符常量相似,可以是:普通字符、轉義序列和通用字符
使用字符串常量時,可以把一個很長的行拆成多個行,可以使用空格分隔各個部分。
這裏是一些字符串常量的實例。
定義常量
常量是使用 const 關鍵字來定義的 。
8. C# 判斷
判斷結構要求程序員指定一個或多個要評估或測試的條件,以及條件為真時要執行的語句(必需的)和條件為假時要執行的語句(可選的)。
? : 運算符
我們已經在前面的章節中講解了 條件運算符 ? :,可以用來替代 if...else 語句。它的一般形式如下:
Exp1 ? Exp2 : Exp3;
9. C# 循環
有的時候,可能需要多次執行同一塊代碼。
一般情況下,語句是順序執行的:函數中的第一個語句先執行,接著是第二個語句,依此類推。
循環控制語句
循環類型
無限循環
如果條件永遠不為假,則循環將變成無限循環。for 循環在傳統意義上可用於實現無限循環。由於構成循環的三個表達式中任何一個都不是必需的,您可以將某些條件表達式留空來構成一個無限循環。
當條件表達式不存在時,它被假設為真。
您也可以設置一個初始值和增量表達式,但是一般情況下,程序員偏向於使用 for(;;) 結構來表示一個無限循環。
10. C# 封裝
封裝 被定義為"把一個或多個項目封閉在一個物理的或者邏輯的包中"。
在面向對象程序設計方法論中,封裝是為了防止對實現細節的訪問。
抽象和封裝是面向對象程序設計的相關特性。
抽象允許相關信息可視化,封裝則使開發者實現所需級別的抽象。
C# 封裝根據具體的需要,設置使用者的訪問權限,並通過 訪問修飾符 來實現。
一個 訪問修飾符 定義了一個類成員的範圍和可見性。
C# 支持的訪問修飾符如下所示:
- Public:所有對象都可以訪問;
- Private:對象本身在對象內部可以訪問;
- Protected:只有該類對象及其子類對象可以訪問
- Internal:同一個程序集的對象可以訪問;
- Protected internal:一個程序集內的對象,或者該類對象及其子類可以訪問;
11. C# 方法
一個方法是把一些相關的語句組織在一起,用來執行一個任務的語句塊。
每一個 C# 程序至少有一個帶有 Main 方法的類。
C# 中調用方法
可以使用方法名調用方法。
也可以使用類的實例從另一個類中調用其他類的公有方法。
遞歸方法調用
一個方法可以自我調用。這就是所謂的 遞歸。
參數傳遞
當調用帶有參數的方法時,您需要向方法傳遞參數。
方式 |
描述 |
值參數 |
這種方式復制參數的實際值給函數的形式參數,實參和形參使用的是兩個不同內存中的值。在這種情況下,當形參的值發生改變時,不會影響實參的值,從而保證了實參數據的安全。 |
引用參數 |
這種方式復制參數的內存位置的引用給形式參數。這意味著,當形參的值發生改變時,同時也改變實參的值。 |
輸出參數 |
這種方式可以返回多個值。 |
按值傳遞參數
這是參數傳遞的默認方式。
在這種方式下,當調用一個方法時,會為每個值參數創建一個新的存儲位置。
實際參數的值會復制給形參,實參和形參使用的是兩個不同內存中的值。
所以,當形參的值發生改變時,不會影響實參的值,從而保證了實參數據的安全。
按引用傳遞參數
引用參數是一個對變量的內存位置的引用。
當按引用傳遞參數時,與值參數不同的是,它不會為這些參數創建一個新的存儲位置。
引用參數表示與提供給方法的實際參數具有相同的內存位置。
在 C# 中,使用 ref 關鍵字聲明引用參數。
按輸出傳遞參數
return 語句可用於只從函數中返回一個值。
但是,可以使用 輸出參數 來從函數中返回兩個值。
輸出參數會把方法輸出的數據賦給自己,其他方面與引用參數相似。
提供給輸出參數的變量不需要賦值。
當需要從一個參數沒有指定初始值的方法中返回值時,輸出參數特別有用。
12. C# 可空類型(Nullable)
C# 提供了一個特殊的數據類型,nullable 類型(可空類型),可空類型可以表示其基礎值類型正常範圍內的值,再加上一個 null 值。
在處理數據庫和其他包含可能未賦值的元素的數據類型時,將 null 賦值給數值類型或布爾型的功能特別有用。
例如,數據庫中的布爾型字段可以存儲值 true 或 false,或者,該字段也可以未定義。
Null 合並運算符( ?? )
Null 合並運算符用於定義可空類型和引用類型的默認值。
Null 合並運算符為類型轉換定義了一個預設值,以防可空類型的值為 Null。Null 合並運算符把操作數類型隱式轉換為另一個可空(或不可空)的值類型的操作數的類型。
如果第一個操作數的值為 null,則運算符返回第二個操作數的值,否則返回第一個操作數的值。
double? num1 = null;
double? num2 = 3.14157;
double num3;
num3 = num1 ?? 5.34;
Console.WriteLine("num3 的值: {0}", num3);
13. C# 數組(Array)
數組是一個存儲相同類型元素的固定大小的順序集合。
數組是用來存儲數據的集合,通常認為數組是一個同一類型變量的集合。
初始化數組
聲明一個數組不會在內存中初始化數組。
當初始化數組變量時,您可以賦值給數組。
數組是一個引用類型,所以您需要使用 new 關鍵字來創建數組的實例。
例如:
double[] balance = new double[10];
賦值給數組
您可以通過使用索引號賦值給一個單獨的數組元素
訪問數組元素
元素是通過帶索引的數組名稱來訪問的。
這是通過把元素的索引放置在數組名稱後的方括號中來實現的。
使用 foreach 循環
在前面的實例中,我們使用一個 for 循環來訪問每個數組元素。
您也可以使用一個 foreach 語句來遍歷數組。
C# 數組細節
在 C# 中,數組是非常重要的,且需要了解更多的細節。下面列出了 C# 程序員必須清楚的一些與數組相關的重要概念:
概念 |
描述 |
多維數組 |
C# 支持多維數組。多維數組最簡單的形式是二維數組。 |
交錯數組 |
C# 支持交錯數組,即數組的數組。 |
傳遞數組給函數 |
您可以通過指定不帶索引的數組名稱來給函數傳遞一個指向數組的指針。 |
參數數組 |
這通常用於傳遞未知數量的參數給函數。 |
Array 類 |
在 System 命名空間中定義,是所有數組的基類,並提供了各種用於數組的屬性和方法。 |
14. C# 字符串(String)
在 C# 中,您可以使用字符數組來表示字符串
但是,更常見的做法是使用 string 關鍵字來聲明一個字符串變量。
string 關鍵字是 System.String 類的別名。
創建 String 對象
您可以使用以下方法之一來創建 string 對象:
- 通過給 String 變量指定一個字符串
- 通過使用 String 類構造函數
- 通過使用字符串串聯運算符( + )
- 通過檢索屬性或調用一個返回字符串的方法
- 通過格式化方法來轉換一個值或對象為它的字符串表示形式
String 類的屬性
String 類有以下兩個屬性:
序號 |
屬性名稱 & 描述 |
1 |
Chars |
2 |
Length |
String 類的方法
String 類有許多方法用於 string 對象的操作。
15. C# 結構(Struct)
在 C# 中,結構是值類型數據結構。
它使得一個單一變量可以存儲各種數據類型的相關數據。
struct 關鍵字用於創建結構。
結構是用來代表一個記錄。
假設您想跟蹤圖書館中書的動態。
定義結構
為了定義一個結構,您必須使用 struct 語句。
struct 語句為程序定義了一個帶有多個成員的新的數據類型。
C# 結構的特點
您已經用了一個簡單的名為 Books 的結構。
在 C# 中的結構與傳統的 C 或 C++ 中的結構不同。
C# 中的結構有以下特點:
- 結構可帶有方法、字段、索引、屬性、運算符方法和事件。
- 結構可定義構造函數,但不能定義析構函數。但是,您不能為結構定義默認的構造函數。默認的構造函數是自動定義的,且不能被改變。
- 與類不同,結構不能繼承其他的結構或類。
- 結構不能作為其他結構或類的基礎結構。
- 結構可實現一個或多個接口。
- 結構成員不能指定為 abstract、virtual 或 protected。
- 當您使用 New 操作符創建一個結構對象時,會調用適當的構造函數來創建結構。與類不同,結構可以不使用 New 操作符即可被實例化。
- 如果不使用 New 操作符,只有在所有的字段都被初始化之後,字段才被賦值,對象才被使用。
類 vs 結構
類和結構有以下幾個基本的不同點:
- 類是引用類型,結構是值類型。
- 結構不支持繼承。
- 結構不能聲明默認的構造函數。
16. C# 枚舉(Enum)
枚舉是一組命名整型常量。
枚舉類型是使用 enum 關鍵字聲明的。
C# 枚舉是值數據類型。
換句話說,枚舉包含自己的值,且不能繼承或傳遞繼承。
枚舉列表中的每個符號代表一個整數值,一個比它前面的符號大的整數值。
17. C# 類(Class)
當你定義一個類時,你定義了一個數據類型的藍圖。
這實際上並沒有定義任何的數據,但它定義了類的名稱意味著什麽,也就是說,類的對象由什麽組成及在這個對象上可執行什麽操作。
對象是類的實例。
構成類的方法和變量稱為類的成員。
類的定義
類的定義是以關鍵字 class 開始,後跟類的名稱。
類的主體,包含在一對花括號內。
請註意:
- 訪問標識符 <access specifier> 指定了對類及其成員的訪問規則。如果沒有指定,則使用默認的訪問標識符。類的默認訪問標識符是 internal,成員的默認訪問標識符是 private。
- 數據類型 <data type> 指定了變量的類型,返回類型 <return type> 指定了返回的方法返回的數據類型。
- 如果要訪問類的成員,你要使用點(.)運算符。
- 點運算符鏈接了對象的名稱和成員的名稱。
成員函數和封裝
類的成員函數是一個在類定義中有它的定義或原型的函數,就像其他變量一樣。
作為類的一個成員,它能在類的任何對象上操作,且能訪問該對象的類的所有成員。
成員變量是對象的屬性(從設計角度),且它們保持私有來實現封裝。
這些變量只能使用公共成員函數來訪問。
C# 中的構造函數
類的 構造函數 是類的一個特殊的成員函數,當創建類的新對象時執行。
構造函數的名稱與類的名稱完全相同,它沒有任何返回類型。
默認的構造函數沒有任何參數。
但是如果你需要一個帶有參數的構造函數可以有參數,這種構造函數叫做參數化構造函數。
這種技術可以幫助你在創建對象的同時給對象賦初始值
C# 中的析構函數
類的 析構函數 是類的一個特殊的成員函數,當類的對象超出範圍時執行。
析構函數的名稱是在類的名稱前加上一個波浪形(~)作為前綴,它不返回值,也不帶任何參數。
析構函數用於在結束程序(比如關閉文件、釋放內存等)之前釋放資源。
析構函數不能繼承或重載。
C# 類的靜態成員
我們可以使用 static 關鍵字把類成員定義為靜態的。
當我們聲明一個類成員為靜態時,意味著無論有多少個類的對象被創建,只會有一個該靜態成員的副本。
關鍵字 static 意味著類中只有一個該成員的實例。
靜態變量用於定義常量,因為它們的值可以通過直接調用類而不需要創建類的實例來獲取。
靜態變量可在成員函數或類的定義外部進行初始化。
你也可以在類的定義內部初始化靜態變量。
你也可以把一個成員函數聲明為 static。
這樣的函數只能訪問靜態變量。
靜態函數在對象被創建之前就已經存在。
18. C# 繼承
繼承是面向對象程序設計中最重要的概念之一。
繼承允許我們根據一個類來定義另一個類,這使得創建和維護應用程序變得更容易。
同時也有利於重用代碼和節省開發時間。
當創建一個類時,程序員不需要完全重新編寫新的數據成員和成員函數,只需要設計一個新的類,繼承了已有的類的成員即可。
這個已有的類被稱為的基類,這個新的類被稱為派生類。
基類的初始化
派生類繼承了基類的成員變量和成員方法。
因此父類對象應在子類對象創建之前被創建。
您可以在成員初始化列表中進行父類的初始化。
C# 多重繼承
多重繼承指的是一個類別可以同時從多於一個父類繼承行為與特征的功能。
與單一繼承相對,單一繼承指一個類別只可以繼承自一個父類。
C# 不支持多重繼承。但是,您可以使用接口來實現多重繼承
19. C# 多態性
多態性意味著有多重形式。
在面向對象編程範式中,多態性往往表現為"一個接口,多個功能"。
多態性可以是靜態的或動態的。
在靜態多態性中,函數的響應是在編譯時發生的。
在動態多態性中,函數的響應是在運行時發生的。
靜態多態性
在編譯時,函數和對象的連接機制被稱為早期綁定,也被稱為靜態綁定。
C# 提供了兩種技術來實現靜態多態性。分別為:
- 函數重載
- 運算符重載
我們討論函數重載。
函數重載
您可以在同一個範圍內對相同的函數名有多個定義。
函數的定義必須彼此不同,可以是參數列表中的參數類型不同,也可以是參數個數不同。
不能重載只有返回類型不同的函數聲明。
實例演示幾個相同的函數 print(),用於打印不同的數據類型.
動態多態性
C# 允許您使用關鍵字 abstract 創建抽象類,用於提供接口的部分類的實現。
當一個派生類繼承自該抽象類時,實現即完成。
抽象類包含抽象方法,抽象方法可被派生類實現。
派生類具有更專業的功能。
請註意,下面是有關抽象類的一些規則:
- 您不能創建一個抽象類的實例。
- 您不能在一個抽象類外部聲明一個抽象方法。
- 通過在類定義前面放置關鍵字 sealed,可以將類聲明為密封類。當一個類被聲明為 sealed 時,它不能被繼承。抽象類不能被聲明為 sealed。
當有一個定義在類中的函數需要在繼承類中實現時,可以使用虛方法。
虛方法是使用關鍵字 virtual 聲明的。
虛方法可以在不同的繼承類中有不同的實現。
對虛方法的調用是在運行時發生的。
動態多態性是通過 抽象類 和 虛方法 實現的。
c#基礎