深入.NET平臺和C#程式設計
目錄:
- .Net框架概述
- C#資料型別
- 集合組織
- 類的方法
- 繼承和多型
- 面向物件原則和特徵
- 可擴充套件標記語言
- 檔案操作
1.概述
- 完全支援面向物件程式設計,提高了軟體的可複用性,可擴充套件性,可維護性和靈活性
- 支援Web、資料庫、雲端計算、SOA
1.1框架體系結構
.NET框架有兩個主要元件:
- CRL是.NET框架的基礎,有兩部分組成:① CLS公共語言規範② CTS通用型別系統
- FCL是一個綜合性的面向物件的可重用型別集合
1.2面向物件
- 類是類別 類是模子 類是物件的資料型別。
設定類的屬性安全:{ get; set; } 只讀;只寫
定義類:類名、定義屬性、定義方法。
- 萬物皆物件 物件也是變數
物件使用:例項化、不同類通過"."操作、類本身可直接使用
- 方法
帶引數的方法(要什麼給什麼)
帶返回值的方法(返回的什麼型別。就用什麼型別變數接收)
- 封裝
保障資料安全,提供清晰對外介面,類的內部可以任意修改。定義類的過程就是對事物的封裝過程。
- 欄位和屬性
欄位儲存資料,不能沒有欄位。屬性不能儲存資料,欄位可有可無。屬性封裝欄位的
2.C#資料型別
- 物件陣列
- 結構
結構是值型別,可以有屬性和方法,不能new,結構中沒建構函式,類中有預設的
訪問修飾符 struct 結構名 {//結構體 }
- 建構函式
預設如果定義了一個類,系統會自動的生成一個和該類名稱相同,並且沒有返回值型別,甚至連Void都沒有的方法,該方法就稱為建構函式!
特殊的值型別:列舉和結構體。特殊的引用型別:陣列和介面。
- 裝箱拆箱
小轉大裝箱。大轉小拆箱。由於裝箱和拆箱過程都要損耗系統的效能,所以在開發中應該儘量避免裝箱和拆箱。
- 值型別傳遞引用型別傳遞
①值型別:
每一個值型別的物件都有一個獨立的記憶體區域儲存自己的值。區域性變數存放在棧中。基本資料型別、列舉型別、結構型別
②引用型別:
要new一個一個拿出來(全部拿給的是地址)。成員變數存放在堆。陣列、類、介面
注意:值型別預設值是0,引用型別為null。
③傳遞:
注意:值傳遞和引用傳遞判定依據是有沒有ref關鍵字
❶如果方法的引數型別本身就是引用型別,那麼對引數值的修改會永久儲存。
❷如果方法的引數型別本身是值型別,又沒有ref修飾,那麼對引數值的修改,不會永久儲存。
❸如果方法的引數型別本身是值型別,但是有ref修飾,那麼物件引數值的修改,也會永久儲存。
3.集合組織
3.1集合
注意:都要設定名稱空間System.Collections。
- ArrayList
Object型別 可維護的動態陣列
索引0開始,可放任意型別,自動填充自動排列調整,獲取元素需型別轉換。
Add() 新增 可以直接使用集合初始化器{ , , }以逗號隔開
RemoveAt() 通過下標刪除
Remove() 通過物件刪除 一次只能移除一個
Clear() 刪除所有集合
ArrayList物件
- Hashtable
ashtable 的資料是通過鍵(Key)和值(Value)來組織
沒下標,每個元素都是一個鍵/值對。Add()有兩個引數 一個表示鍵(不能重複),一個鍵表示所對應的值。
3.2泛型和泛型集合
注意:集合來儲存資料,可以以最大限度重用程式碼、保護安全。提升效能 不用做型別轉換 。把資料型別作為引數:泛型
- List<T>
<T>對型別進行約束,T表明集合中管理的元素型別
語法: List<T> 物件名=new List<T>(); “<T>”中的T可以對集合中的元素型別進行約束,T表明集合中管理的元素型別 示例: //建立工程師員工集合 List<SE> list=new List<SE>(); //初始化三個工程師員工 SE jack=new SE(); //屬性賦值 jack.ID="001"; jack.Name="張三"; SE joe=new SE(); //賦值省略。。。 //將元素新增到集合中 list.Add(jack); list.Add(joe); 示例: //通過索引訪問 SE se=list[0]; //通過索引或者物件刪除 list.RemoveAt(0); list.Remove(joe); //遍歷 foreach(SE sein list) { //遍歷時無需型別轉換 MessageBox.Show(se.SayHi()); }List<T>語法
- Dictionary<K,V>
可以通過K獲取Value
語法: Dictionary<K,V> 物件名=new Dictionary<K,V>(); 說明:<K,V>中的K表示集合中Key的型別,V表示Value的型別 示例: //建立工程師員工集合 Dictionary<string,SE> list=new Dictionary<string,SE>(); //初始化三個工程師員工 SE jack=new SE(); //屬性賦值 jack.ID="001"; jack.Name="張三"; SE joe=new SE(); //屬性賦值省略 //新增元素 list.Add(jack.ID,jack); list.Add(joe.ID,ema); //列印集合中元素數目 MessageBox.Show(string.Format("部門共包括{0}個工程師。",list.Count.ToString())); //通過Key訪問元素 SE se=list["001"]; //通過key刪除元素 list.Remove("001"); //遍歷 foreach(SE se in list.Values) { //遍歷時無需型別轉換 MessageBox.Show(se.SayHi()); }Dictionary<K,V>
- 泛型類
public Class 類名<T> 可以封裝不是特定於具體資料型別的操作 支援任意資料型別
4.類的方法
- 建構函式
方法名與類名相同、沒有返回值型別、通常用來初始化物件 分配欄位的儲存空間並給初始值
無參建構函式:缺點:物件例項化的值是固定的
帶參建構函式:優點:靈活性好,通過引數來動態控制物件的特徵、建立物件也可以使用物件初始化器 "{}"
注意:呼叫帶餐函式一定要使傳入的引數和引數列表相對應。C#規定:一旦有了建構函式,就不在自動分配建構函式
語法:(無參建構函式) 訪問修飾符 類名() { //方法體 } 示例: public class SE { //無參建構函式:設定屬性初始值 public SE() { this.ID="000"; this.Age=20; this.Name="張三"; this.Gender=Gender.male; } } 語法:(帶參建構函式) 訪問修飾符 類名(引數列表) { //方法體 }建構函式
- 方法過載
建構函式的過載就是:允許在同一個類中定義多個相同方法名,但引數列表(引數個數,引數型別)不同的方法
注意:要寫上預設建構函式
特點:方法名相同、方法引數型別不同或引數個數不同、在同一個類中、傳值要準確
優點:方法過載不僅能避免命名的麻煩,還可以使呼叫者不必判讀方法名就可以直接使用
四步驟:瞭解需求、找類、找類的屬性方法、實列化物件
- 物件互動
在面向物件中,物件和物件之間也存在著類似的關係("蟻巢")。
注意:不執行時沒有任何互動,在事件等外力的作用下,物件和物件之間就開始相互協調工作每個類都有自己的特性和功能,我們把他封裝為屬性和方法 物件之間通過屬性和方法進行互動,可以認為方法的引數及方法的返回值都是物件間相互傳遞的訊息總之物件互動主要通過引數傳遞、方法呼叫及屬性操作來實現
5.繼承和多型
- 繼承
好處:優化程式碼結構,讓類和類產生關係。減少冗餘提高複用性。為多型提供前提。
使用方法:子類繼承父類,使用“”:“”冒號關鍵字,子類中可以訪問到父類中定義的成員。
執行過程:建立子類時 先執行父類在執行子類本身的類 先會呼叫無參構造 可以用base指定呼叫父類的哪一個建構函式
遍歷集合:只需要對每個物件的型別進行判斷(is關鍵字判斷是否屬於給定的型別)
修飾符:強度:public>protected>private。特殊關鍵字:sealed,用它修飾的類是不能被繼承的,稱密封類
注意:一個父類也稱基類可以有多個子類,一個子類也稱派生類只能有一個父類。
//Emp類的建構函式 public Emp(string id,int age,stirng name,Gender gender) { this.ID=id; this.Age=age; this.Name=name; this.Gender=gender; } //SE類的建構函式 public SE(string id,stirng name,int age,Gender gender,int popularity): base(id,age,name,gender) { //繼承自父類 的屬性 //呼叫父類的建構函式可以替換掉的程式碼 // this.ID=id; //this.Age=age; //this.Name=name; //this.Gender=gender; //SE類的擴充套件屬性 this.Popularity=popularity; }base用法
- 多型
語法: 訪問修飾符 virtual 返回型別 方法名() { //方法體 } 在子類中這樣定義 public override string SayHi() { //方法體 }多型語法
多型是建立在繼承關係之上的。同一個命令對很多人執行,根據不同的環境執行不同的行為。在繼承關係的前提下,例項化出不同的物件,這些物件呼叫相同的方法,但卻表現出不同的行為,叫多型。
多型三種:
- 虛方法
object是所有類的基類,virtual 關鍵字 稱為虛方法,虛方法無方法體,override 關鍵字 稱為方法的重寫 (必須要有虛方法)
注意: 如果子類不重寫父類的虛方法,直接執行父類的預設實現。如果子類重寫了父類的虛方法,執行子類重寫後的方法
- 抽象類
當我們父類中的虛方法已經虛到完全無法確定方法體的時候,就可以用抽象方法
注意:抽象類中不一定要有抽象方法,抽象方法必須存在於抽象類中。抽象方法必須被自類重寫,除非子類也是抽象方法。不能例項化抽象類為物件
- 介面
介面使用 interface關鍵字定義,沒有Class關鍵字,介面名一般使用"Ixxx" (i開頭)。
好處:介面是一種規範和標準,約束類的行為, 介面也表示一種能力。利於程式碼的擴充套件和維護。一個類可以實現多個介面,用逗號隔開。一個介面可以繼承多個介面,逗號隔開
注意:介面不能包含欄位,但可以包含屬性,不能有實現的東西,不能包含常量變數,也不能包含任何靜態成員。介面、抽象類、私有的建構函式都不能例項化。介面成員不許新增訪問符,預設是public。介面所有方法都是抽象方法
6.面向對原則和特徵
面向物件六大原則:
①單一職責原則
②開閉原則
③里氏轉換原則
子類物件可以直接賦值給父類變數,可以呼叫父類的成員,父類物件只能掉自己的。
④依賴倒置原則
⑤介面隔離原則
⑥迪米特原則
面向物件三大特徵:
封裝:保證物件自身資料的完整性和安全性。
繼承:建立類之間的關係,實現程式碼複用,方便系統的擴充套件。
多型:相同的方法呼叫可實現不同的實現方式。
注意:is 如果正確返回true,錯誤返回false;as 如果成功返回對應的物件,否則返回null
7.可擴充套件標記語言
可擴充套件標記語言 標記語言。非常靈活的語言,沒有固定標籤,所有標籤都可以自定義。通常被用於資訊的記錄和傳遞,經常被充當配置檔案
特點:xml要有且只有一個根元素。大小寫敏感,標籤成對的,且要正確巢狀。
物件:XmlDocument 表示整個文件XmlNode 表示一個節點 InnerText獲取節點的值 Name獲取節點的名字 ChildNodes 獲取節點的所有子節點
Channel 各個子節點 DocumentElenment 獲取根節點 Nodes獲取子節點集合
//解析XML static void Main(string[] args) { //讀取Xml檔案方式 #region 方式一 XmlDocument doc = new XmlDocument(); //繫結檔案 doc.Load("Books.xml"); //將整篇文件中的根節點玲出來 XmlNode root = doc.DocumentElement; //根據root,找所有子節點的集合 root.ChildNodes foreach (XmlNode item in root.ChildNodes) { //一個item就是一個book foreach (XmlNode child in item.ChildNodes) { //一個child代表一本書的單個屬性 switch (child.Name) { case "name": Console.Write(child.InnerText); break; case "age": Console.Write(child.InnerText); break; case "sex": Console.WriteLine(child.InnerText); break; default: break; } } Console.WriteLine("================="); }解析XML
#region 方式二 XmlDocument doc = new XmlDocument(); doc.Load("student.xml"); XmlNode no = doc.DocumentElement; foreach (XmlNode item in no.ChildNodes ) { //string name=item["name"].InnerText; //string age = item["age"].InnerText; //string sex = item["sex"].InnerText; Console.WriteLine("姓名:" + item["name"].InnerText); Console.WriteLine("年齡:" + item["age"].InnerText); Console.WriteLine("性別:" + item["sex"].InnerText); Console.WriteLine("======================="); }方式二
8.檔案操作
- 五步驟:
首先需要引入 System.IO 名稱空間
①建立檔案流
②建立閱讀或者寫入器
③執行讀寫操作
④關閉閱讀或者寫入器
⑤關閉檔案流
- 解決亂碼問題
程式設計時給檔案讀取器物件指定對應的編碼格式。Encoding 靜態成員指定編碼格式。Encoding.UTF8; Encoding.Default 獲取作業系統的當前編碼
//建立檔案流 FileStream myfs=new FileStream (String filepath,FileMode fileMode); filePath 用於指定要操作的檔案 fileMode 指定開啟檔案的模式(FileMode 列舉型別) Create:用指定的名稱新建一個檔案,如果檔案存在,則改寫舊檔案 CreateNew: 新建一個檔案,如果檔案存在會發生異常,提示檔案已經存在 Open: 開啟一個檔案,指定的檔案必須存在 OpenOrCreate:如果檔案不存在,則用指定的名稱新建一個檔案並開啟它 Append:開啟現有檔案,並在檔案末尾追加內容 //檔案讀寫器 1.Stream Write寫入器(用於將資料寫入檔案流) Stream Write.Write();用於寫入流,這個流就是我們建立的檔案流 Stream Write.WriteLine();用於寫入一行資料,寫入某些資料後跟換行符 Stream Write.close();關閉寫入器 2.StreamReader 讀取器 (讀取流中的資料) StreamReader.ReadLine();讀取檔案流中的一行資料,並返回字串 StreamReader.ReadToEnd(); 從當前位置讀到末尾,返回字串 StreamReader.close(); 關閉讀取器 //檔案和目錄操作 File (提供檔案操作) Exists(string Path) 用於檢查指定檔案是否存在 bool型別 Copy(string yi,string er)賦值到另外一個路徑,不存在新建一個 Move(string yi,string er)將指定檔案移動到一個新路徑 Delete(string path) 刪除指定檔案,不存在也不異常 Directory(提供資料夾操作) Exists(string Path) 用於檢查指定資料夾是否存在 bool型別 Move(string yi,string er)將指定資料夾移動到一個新路徑 Delete(string path,bool recursive) 刪除指定目錄,如果recursive為true,刪除子目錄中的所有內容 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace Wenj { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //讀取 private void button1_Click(object sender, EventArgs e) { FileStream fs = new FileStream("D:\\Happy.txt",FileMode.Open); byte [] bytes=new byte [1024]; int count= fs.Read(bytes,0,bytes .Length); if (bytes!=null ) { string result = Encoding.Default.GetString(bytes, 0, count); txt1.Text = result; count = fs.Read(bytes, 0, bytes.Length); } fs.Close(); } //寫入 private void button2_Click(object sender, EventArgs e) { FileStream fswrite = new FileStream("D:\\Happy.txt", FileMode.Append ); string word = txt1.Text; byte[] bytes = Encoding.Default.GetBytes(word); fswrite.Write(bytes, 0, bytes.Length); MessageBox.Show("寫入成功"); fswrite.Close(); } //複製 private void button3_Click(object sender, EventArgs e) { string fpath = ""; string tpath = ""; FileStream fromfs = new FileStream(fpath, FileMode.Open); FileStream tofs = new FileStream(tpath, FileMode.Create ); byte [] bytes=new byte [1024]; int count = fromfs.Read(bytes ,0,bytes .Length); //int i = 0; while (count !=0) { tofs.Write(bytes ,0,bytes .Length); count = fromfs.Read(bytes, 0, bytes.Length); MessageBox.Show("成功"); } tofs.Close(); fromfs.Close(); } private void Form1_Load(object sender, EventArgs e) { } } }檔案操作