.net 讀書筆記

来源:http://www.cnblogs.com/roucheng/archive/2016/05/06/dushubiji.html
-Advertisement-
Play Games

好書不能只讀一遍,這兩天又翻看了一遍《你必須知道的.NET》,重溫了下基礎,重溫了下經典,簡單記錄了下來。 記憶體分配:CLR 管理記憶體的區域,主要有三塊,分別為: 線程的堆棧,用於分配值類型實例。堆棧主要由操作系統管理,而不受垃圾收集器的控制,當值類型實例所在方法結束時,其存儲單位自動釋放。棧的執行 ...


好書不能只讀一遍,這兩天又翻看了一遍《你必須知道的.NET》,重溫了下基礎,重溫了下經典,簡單記錄了下來。

記憶體分配:
CLR 管理記憶體的區域,主要有三塊,分別為:

線程的堆棧,用於分配值類型實例。堆棧主要由操作系統管理,而不受垃圾收集器的控制,當值類型實例所在方法結束時,其存儲單位自動釋放。棧的執行效率高,但存儲容量有限。

GC 堆,用於分配小對象實例。如果引用類型對象的實例大小小於 85000 位元組,實例將被分配在 GC 堆上,當有記憶體分配或者回收時,垃圾收集器可能會對 GC 堆進行壓縮,詳情見後文講述。

LOH(Large Object Heap)堆,用於分配大對象實例。如果引用類型對象的實例大小不小於 850
00 位元組時,該實例將被分配到 LOH 堆上,而 LOH 堆不會被壓縮,而且只在完全 GC 回收時被回收。


堆棧的記憶體分配機制:
對於值類型來說,一般創建線上程的堆棧上。但並非所有的值類型都創建線上程的堆棧上,例如作為類的欄位時,值類型作為實例成員的一部分也被創建在托管堆上;裝箱發生時,值類型欄位也會拷貝在托管堆上。

引用類型的實例分配於托管堆上,而線程棧卻是對象生命周期開始的地方。對 32 位處理器來說,應用程式完成進程初始化後,CLR 將在進程的可用地址空間上分配一塊保留的地址空間,它是進程(每個進程可使用 4GB)中可用地址空間上的一塊記憶體區域,但並不對應於任何物理記憶體,這塊地址空間即是托管堆。
托管堆又根據存儲信息的不同劃分為多個區域,其中最重要的是垃圾回收堆(GC Heap)和載入堆(Loader Heap),GC Heap 用於存儲對象實例,受 GC 管理;Loader Heap 又分為 High-Frequency Heap、Low-Frequency Heap 和 Stub Heap,不同的堆上又存儲不同的信息。Loader Heap 最重要的信息就是元數據相關的信息,也就是 Type 對象,每個 Type 在 Loader Heap 上體現為一個 Method Table(方法表),而 Method Table 中則記錄了存儲的元數據信息,例如基類型、靜態欄位、實現的介面、所有的方法等等。Loader Heap 不受 GC 控制,其生命周期為從創建到 AppDomain 卸載。

在進入實際的記憶體分配分析之前,有必要對幾個基本概念做以交代,以便更好的在接下來的分析中展開討論。
TypeHandle,類型句柄,指向對應實例的方法表,每個對象創建時都包含該附加成員,並且占用 4 個位元組的記憶體空間。我們知道,每個類型都對應於一個方法表,方法表創建於編譯時,主要包含了類型的特征信息、實現的介面數目、方法表的 slot 數目等。

SyncBlockIndex,用於線程同步,每個對象創建時也包含該附加成員,它指向一塊被稱為 Synchronization Block 的記憶體塊,用於管理對象同步,同樣占用 4 個位元組的記憶體空間。

NextObjPtr,由托管堆維護的一個指針,用於標識下一個新建對象分配時在托管堆中所處的位置。CLR 初始化時,NextObjPtr 位於托管堆的基地址。

在托管堆中增加新的實例對象,只是將 NextObjPtr 指針增加一定的數值,再次新增的對象將分配在當前 NextObjPtr 指向的記憶體空間,因此在托管堆棧中,連續分配的對象在記憶體中一定是連續的,這種分配機制非常高效。

http://www.cnblogs.com/roucheng/p/netkuangjia.html
靜態欄位的記憶體分配和釋放,又有何不同?
靜態欄位也保存在方法表中,位於方法表的槽數組後,其生命周期為從創建到 AppDomain卸載。因此一個類型無論創建多少個對象,其靜態欄位在記憶體中也只有一份。靜態欄位只能由靜態構造函數進行初始化,靜態構造函數確保在類型任何對象創建前,或者在任何靜態欄位或方法被引用前執行,其詳細的執行順序請參考相關討論。

繼承,就是面向對象中類與類之間的一種關係。繼承的類稱為子類、派生類,而被繼承類稱為父類、基類或超類。通過繼承,使得子類具有父類的屬性和方法,同時子類也可以通過加入新的屬性和方法或者修改父類的屬性和方法建立新的類層次。
繼承機制體現了面向對象技術中的復用性、擴展性和安全性。為面向對象軟體開發與模塊化軟體架構提供了最基本的技術基礎。

Adapter 模式主要用於
將一個類的介面轉換為另外一個介面,通常情況下在改變原有體系的條件下應對新的需求變化,通過引入新的適配器類來完成對既存體系的擴展和改造。Adapter 模式就其實現方式主要包括:類的 Adapter 模式。通過引入新的類型來繼承原有類型,同時實現新加入的介面方法。其缺點是耦合度高,需要引入過多的新類型。對象的 Adapter 模式。通過聚合而非繼承的方式來實現對原有系統的擴展,鬆散耦合,較少的新類型。

繼承:
密封類不可以被繼承。
繼承關係中,我們更多的是關註其共性而不是特性,因為共性是層次復用的基礎,而特性是系統擴展的基點。
實現單繼承,介面多繼承。
從巨集觀來看,繼承多關註於共通性;而多態多著眼於差異性。
繼承的層次應該有所控制,否則類型之間的關係維護會消耗更多的精力。
面向對象原則:多組合,少繼承;低耦合,高內聚。

.NET 中對象的繼承兩個原則:
1.關註對象原則:調用子類還是父類的方法,取決於創建的對象是子類對象還是父類對象,而不是它的引用類型。例如 Bird bird2 = new Chicken()時,我們關註的是其創建對象為 Chicken 類型,因此子類將繼承父類的欄位和方法,或者覆寫父類的虛方法,而不用關註 bird2 的引用類型是否為Bird。引用類型不同的區別決定了不同的對象在方法表中不同的訪問許可權。
根據關註對象原則,那麼下麵的兩種情況又該如何區別呢?
Bird bird2 = new Chicken();
Chicken chicken = new Chicken();
根據我們上文的分析,bird2 對象和 chicken 對象在記憶體佈局上是一樣的,差別就在於其引用指針的類型不同:bird2 為 Bird 類型指針,而 chicken 為 Chicken 類型指針。以方法調用為例,不同的類型指針在虛擬方法表中有不同的附加信息作為標誌來區別其訪問的地址區域,稱為 offset。不同類型的指針只能在其特定地址區域內進行執行,子類覆蓋父類時會保證其訪問地址區域的一致性,從而解決了不同的類型訪問具有不同的訪問許可權問題。

2. 執行就近原則:對於同名欄位或者方法,編譯器是按照其順序查找來引用的,也就是首先訪問離它創建最近的欄位或者方法,例如上例中的 bird2,是 Bird 類型,因此會首先訪問 Bird_type(註意編譯器是不會重新命名的,在此是為區分起見),如果 type 類型設為 public,則在此將返回 Bird 值。這也就是為什麼在對象創建時必須將欄位按順序排列,而父類要先於子類編譯的原因了。

封裝:
在面向對象三要素中,封裝特性為程式設計提供了系統與系統、模塊與模塊、類與類之間交互的實現手段。
封裝隱藏了類內部的具體實現細節,對外則提供統一訪問介面,來操作內部數據成員。這樣實現的好處是實現了 UI 分離,程式員不需要知道類內部的具體實現,只需按照介面協議進行控制即可。同時對類內部來說,封裝保證了類內部成員的安全性和可靠性。

欄位,屬性,方法
通常系統需求描述的核心名詞,可以抽象為類,而對這些名詞驅動的動作,可以對應地抽象為方法。當然,具體的設計思路要根據具體的需求情況,在整體架構目標的基礎上進行有效的篩選、剝離和抽象。取捨之間,彰顯 OO 智慧與設計模式的魅力。

欄位(field)
通常定義為 private,表示類的狀態信息。
封裝的第一個原則就是:將欄位定義為 private。
封裝原則告訴我們:類的欄位信息最好以私有方式提供給類的外部,而不是以公有方式來實現,否則不適當的操作將造成不必要的錯誤方式,破壞對象的狀態信息,數據安全性和可靠性無法保證。

屬性(property)
通常定義為 public,表示類的對外成員。
欄位設置為了private,則需要通過屬性對外進行暴露。
編譯器的執行邏輯是:如果發現一個屬性,並且查看該屬性中實現了 get 還是 set,就對應地生成 get_屬性名、set_屬性名兩個方法。因此,我們可以說,屬性的實質其實就是在編譯時分別將 get 和 set 訪問器實現為對外方法,從而達到控制屬性的目的,而對屬性的讀寫行為伴隨的實際是一個相應方法的調用,它以一種簡單的形式實現了方法。
通過對公共屬性的訪問來實現對類狀態信息的讀寫控制,主要有兩點好處:一是避免了對數據安全的訪問限制,包含內部數據的可靠性;二是避免了類擴展或者修改帶來的變數連鎖反應。
還有一種含參屬性,在 C#中稱為索引器(indexer),對 CLR 來說並沒有含不含參數的區別,它只是負責將相應的訪問器實現為對應的方法,不同的是含參屬性中加入了對參數的處理過程罷了。

方法(method)
封裝了類的行為,提供了類的對外表現。用於將封裝的內部細節以公有方法提供對外介面,從而實現與外部的交互與響應。
從上面屬性的分析我們可知,實際上對屬性的讀寫就是通過方法來實現的。因此,對外交互的方法,通常實現為 public。

多態
分類:根據其實現的方式我們可以進一步分為基類繼承式多態和介面實現式多態。
運行機制:從技術實現角度來看,是.NET 的動態綁定機製成就了面向對象的多態特性。
動態綁定,又叫晚期綁定,是區別與靜態綁定而言的。靜態綁定在編譯期就可以確定關聯,一般是以方法重載來實現的;而動態綁定則在運行期通過檢查虛擬方法表來確定動態關聯覆寫的方法,一般以繼承和虛方法來實現。嚴格來講,.NET 中並不存在靜態綁定。所有的.NET 源文件都首先被編譯為 IL 代碼和元數據,在方法執行時,IL 代碼才被 JIT 編譯器即時轉換為本地 CPU 指令。JIT 編譯發生於運行時,因此也就不存在完全在編譯期建立的關聯關係,靜態綁定的概念也就無從談起。
意義:多態提供了對同一類對象的差異化處理方式,實現了對變化和共性的有效封裝和繼承,體現了“一個介面,多種方法”的思想,使方法抽象機製成為可能。在.NET 中,預設情況下方法是非虛的,以 C#為例必須顯式地通過 virtual 或者 abstract 標記為虛方法或者抽象方法,以便在子類中覆寫父類方法。在面向對象的基本要素中,多態和繼承、多態和重載存在緊密的聯繫,正如前文所述多態的基礎就是建立有效的繼承體系,因此繼承和重載是多態的實現基礎。

介面
所謂介面,就是契約,用於規定一種規則由大家遵守。所以,.NET 中很多的介面都以 able 為命名尾碼,例如 INullable、ICloneable、IEnumerable、IComparable 等,意指能夠為空、能夠克隆、能夠枚舉、能夠對比,其實正是對契約的一種遵守寓意,只有實現了 ICloneable 介面的類型,才允許其實例對象被拷貝。

面向介面編程就意味著,在自定義類中想要有某種特性,就必須遵守這種契約。
interface IDriveable
{
void Drive();
}

public class BusDriver : IDriveable
{
public void Drive()
{
Console.WriteLine("有經驗的司機可以駕駛公車。");
}
}
同樣例如要使用 foreach 語句迭代,其前提是操作類型必須實現 IEnumerable 介面,這也是一種契約。
實現介面還意味著,同樣的方法對不同的對象表現為不同的行為。
本質:因此介面其實本質上可以看作是一個定義了抽象方法的類,該類僅提供了方法的定義,而沒有方法的實現,其功能由介面的實現類來完成。
另外,按照介面隔離原則,介面應該被實現為具有單一功能的多個小介面,而不是具有多個功能的大介面。通過多個介面的不同組合,客戶端按需實現不同的介面,從而避免出現介面污染的問題。

關於介面的規則,可以有以下的歸納:
介面隔離原則強調介面應該被實現為具有單一功能的小介面,而不要實現為具有多個功能的胖介面,類對於類的依賴應建立在最小的介面之上。
介面支持多繼承,既可以作用於值類型,也可以作用於引用類型。
禁止為已經發佈的介面,添加新的成員,這意味著你必須重新修改所有實現了該介面的類型,在實際的應用中,這往往是不可能完成的事情。
介面不能被實例化,沒有構造函數,介面成員被隱式聲明為 public。
介面可以作用於值類型和引用類型,並且支持多繼承。

 

.NET開發性能優化條款:
1.資源的釋放:推薦以 Dispose 模式來代替 Finalize 方式。
2.選擇合適的垃圾收集器:工作站 GC 和服務期 GC。
3.在適當的情況下對對象實現弱引用。
弱引用是對象引用的一種 中間態 ,實現了對象既可以通過 GC 回收其記憶體,又可被應用程式訪問的機制。在.NET中,WeakReference 類用於表示弱引用,通過其 Target 屬性來表示要追蹤的對象,通過其值賦給變數來創建目標對象的強引用.
4.儘可能以 using 來執行資源清理。
5.推薦使用泛型集合來代替非泛型集合。
6.初始化時最好為集合對象指定大小。
7.特定類型的 Array 性能優於 ArrayList。
8.字元串駐留機制,是 CLR 為 String 類型實現的特殊設計。
String 類型無疑是程式設計中使用最頻繁、應用最廣泛的基元類型,因此 CLR 在設計上為了提升 String類型性能考慮,實現了一種稱為 字元串駐留 的機制,從而實現了相同
字元串可能共用記憶體空間。同時,字元串駐留是進程級的,垃圾回收不能釋放 CLR 內部哈希表維護的字元串對象,只有進程結束時才釋放。這些機制均為 String類型的性能提升
和記憶體優化提供了良好的基礎。
9.合理使用 System.String 和 System.Text.StringBuilder。
10.儘量在子類中重寫 ToString 方法。
ToString 方法是 System.Object 提供的一個公有的虛方法,.NET 中任何類型都可繼承 System.Object 類型提供的實現方法,預設為返回類型全路徑名稱。在自定義類或結構中重寫 ToString 方法,除了可以有效控制輸出結果,還能在一定程度上減少裝箱操作的發生。
11.for 和 foreach 的選擇。
推薦選擇 foreach 來處理可枚舉集合的迴圈結構
12.以多線程處理應對系統設計。
13.儘可能少地拋出異常,禁止將異常處理放在迴圈內。
14.捕獲異常時,catch 塊中儘量指定具體的異常篩選器,多個 catch 塊應該保證異常由特殊到一般的排列順序。
15.以 is/as 模式進行類型相容性檢查。
以 is 來實現類型判斷,以 as 實現安全的類型轉換,是值得推薦的方法。
16.const 和 static readonly 的權衡。
const 是編譯時常量,readonly 是運行時常量,所以 const 高效,readonly 靈活。在實際的應用中,推薦以 static readonly來代替 const,以解決 const 可能引起的程式集引用不一致問題,還有帶來的較多靈活性控制。
17.儘量避免不當的裝箱和拆箱,選擇合適的代替方案。
18.儘量使用一維零基數組。
19.CLR 對一維零基數組使用了特殊的 IL 操作指令 newarr,在訪問數組時不需要通過索引減去偏移量來完成,而且 JIT也只需執行一次範圍檢查,可以大大提升訪問性能
20.以 FxCop 工具,檢查你的代碼。
FxCop 是微軟開發的一個針對.NET 托管環境的代碼分析工具

 

new 關鍵字深入淺出
作為運算符, 用於創建對象和調用構造函數。作為修飾符,用於向基類成員隱藏繼承成員。作為約束,用於在泛型聲明中約束可能用作類型參數的參數的類型。
MSDN 中的定義是:new 約束指定泛型類聲明中的任何類型參數都必須有公共的無參數構造函數。當泛型類創建類型的新實例時,將此約束應用於類型參數。

base 關鍵字
其用於在派生類中實現對基類公有或者受保護成員的訪問,但是只局限在構造函數、實例方法和實例
屬性訪問器中,MSDN 中小結的具體功能包括:
調用基類上已被其他方法重寫的方法。
指定創建派生類實例時應調用的基類構造函數。
this 關鍵字
其用於引用類的當前實例,也包括繼承而來的方法,通常可以隱藏 this,MSDN 中的小結功能主要包
括:
限定被相似的名稱隱藏的成員
將對象作為參數傳遞到其他方法
聲明索引器

 

class和struct相關
1.class 是引用類型,繼承自 System.Object 類;struct 是值類型,繼承自 System.ValueType類,因此不具多態性。但是註意,System.ValueType 是個引用類型。
2.從職能觀點來看,class 表現為行為;而 struct 常用於存儲數據。
3.class 支持繼承,可以繼承自類和介面;而 struct 沒有繼承性,struct 不能從 class 繼承,也不能作為 class 的基類,但 struct 支持介面繼承
4.class 可以聲明無參構造函數,可以聲明析構函數;而 struct 只能聲明帶參數構造函數,且不能聲明析構函數。因此,struct 沒有自定義的預設無參構造函數,預設無參構造器只是簡單地把所有值初始化為它們的 0 等價值
5.實例化時,class 要使用 new 關鍵字;而 struct 可以不使用 new 關鍵字,如果不以 new 來實例化 struct,則其所有的欄位將處於未分配狀態,直到所有欄位完成初始化,否則引用未賦值的欄位會導致編譯錯誤。
6.class 可以實抽象類(abstract),可以聲明抽象函數;而 struct 為抽象,也不能聲明抽象函數。
7.class 可以聲明 protected 成員、virtual 成員、sealed 成員和 override 成員;而 struct 不可以,但是值得註意的是,struct 可以重載 System.Object 的 3 個虛方法,Equals()、ToString()和GetHashTable()。
8.class 的對象複製分為淺拷貝和深拷貝(該主題我們在本系列以後的主題中將重點講述,本文不作詳述),必須經過特別的方法來完成複製;而 struct 創建的對象複製簡單,可以直接以等號連接即可。
9.class 實例由垃圾回收機制來保證記憶體的回收處理;而 struct 變數使用完後立即自動解除記憶體分配。
10.作為參數傳遞時,class 變數是以按址方式傳遞;而 struct 變數是以按值方式傳遞的。


介面和抽象類的區別:
1介面支持多繼承;抽象類不能實現多繼承。
2介面只能定義抽象規則;抽象類既可以定義規則,還可能提供已實現的成員。
3介面是一組行為規範;抽象類是一個不完全的類,著重族的概念。
4介面可以用於支持回調;抽象類不能實現回調,因為繼承不支持。
5介面只包含方法、屬性、索引器、事件的簽名,但不能定義欄位和包含實現的方法;抽象類可以定義欄位、屬性、包含有實現的方法。
6介面可以作用於值類型和引用類型;抽象類只能作用於引用類型。例如,Struct 就可以繼承介面,而不能繼承類。


介面和抽象類適用的場合:
1抽象類應主要用於關係密切的對象,而介面最適合為不相關的類提供通用功能。
2介面著重於 CAN-DO 關係類型,而抽象類則偏重於 IS-A 式的關係;
3介面多定義對象的行為;抽象類多定義對象的屬性;
4介面定義可以使用 public、protected、internal 和 private 修飾符,但是幾乎所有的介面都定義為 public,原因就不必多說了。
5介面不變 ,是應該考慮的重要因素。所以,在由介面增加擴展時,應該增加新的介面,而不能更改現有介面。
6儘量將介面設計成功能單一的功能塊,以.NET Framework 為例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable 等都只包含一個公共方法。
7介面名稱前面的大寫字母 I 是一個約定,正如欄位名以下劃線開頭一樣,請堅持這些原則。
8在介面中,所有的方法都預設為 public。
9如果預計會出現版本問題,可以創建 抽象類 。例如,創建了狗(Dog)、雞(Chicken)和鴨(Duck),那麼應該考慮抽象出動物(Animal)來應對以後可能出現風馬牛的事情。而向介面中添加新成員則會強制要求修改所有派生類,並重新編譯,所以版本式的問題最好以抽象類來實現。
10從抽象類派生的非抽象類必須包括繼承的所有抽象方法和抽象訪問器的實實現。
11對抽象類不能使用 new 關鍵字,也不能被密封,原因是抽象類不能被實例化。
12在抽象方法聲明中不能使用 static 或 virtual 修飾符。

 

System.Object
System.Object 是所有類型的基類,任何類型都直接或間接繼承自 System.Object 類。沒有指定基類的類型都預設繼承於 System.Object,從而具有 Object 的基本特性,這些特性
主要包括:
通過 GetType 方法,獲取對象類型信息。
通過 Equals、ReferenceEquals 和==,實現對象判等。
通過 ToString 方法,獲取對象字元串信息 ,預設返回對象類型全名。
通過 MemberwiseClone 方法,實現對象實例的淺拷貝。
通過 GetHashCode 方法,獲取對象的值的散列碼。
通過 Finalize 方法,在垃圾回收時進行資源清理。


委托,事件,匿名方法,Lambda表達式
委托本質上仍舊是一個類,該類繼承自System.MulticastDelegate類,該類維護一個帶有鏈接的委托列表,在調用多播委托時,將按照委托列表的委托順序而調用的。還包括一個接受兩個參數的構造函數和3個重要方法:BeginInvoke、EndInvoke和Invoke。
委托的構造函數中包括了兩個參數:第一個參數表示一個對象引用,它指向了當前委托調用回調函數的實例,第二個參數標識了回調方法。創建完實例化對象都後,通過Invoke執行回調方法調用,可見真正執行調用的是Invoke方法。

.NET的事件模型建立在委托機制之上,透徹的瞭解了委托才能明白的分析事件。可以說,事件是對委托的封裝,從委托的示例中可知,在客戶端可以隨意對委托進行操作,一定程度上破壞了面向的對象的封裝機制,因此事件實現了對委托的封裝。。
完整定義過程:
定義一個內部事件參數類型,用於存放事件引發時向事件處理程式傳遞的狀態信息,EventArgs是事件數據類的基類。
聲明事件委托,主要包括兩個參數:一個表示事件發送者對象,一個表示事件參數類對象。定義事件成員。
定義負責通知事件引發的方法,它被實現為protected virtual方法,目的是可以在派生類中覆寫該方法來拒絕監視事件。
定義一個觸發事件的方法,例如Calculate被調用時,表示有新的計算發生。

匿名方法以內聯方式放入委托對象的使用位置,而避免創建一個委托來關聯回調方法,也就是由委托調用了匿名的方法,將方法代碼和委托實例直接關聯,在語法上有簡潔和直觀的好處。

Lambda表達式是Functional Programming的核心概念,現在C# 3.0中也引入了Lambda表達式來實現更加簡潔的語法,並且為LINQ提供了語法基礎。

小結:
委托實現了面向對象的,類型安全的方法回調機制。 
以Delegate作為委托類型的尾碼,以EventHandle作為事件委托的尾碼,是規範的命名規則。 
多播委托返回值一般為void,不推薦在多播委托中返回非void的類型。
匿名方法和Lambda表達式提供了更為簡潔的語法表現,而這些新的特性主要是基於編譯器而實現的,在IL上並沒有本質的變化。
.NET的事件是Observer模式在委托中的應用,並且基於.NET規範而實現,體現了更好的耦合性和靈活性。

http://hovertree.com/menu/dotnet/
.NET中的異常
而對異常的理解往往存在或多或少的誤解:
例如:異常就是程式錯誤,以錯誤代碼返回錯誤信息就足夠了。在系統中異常越多越能保證容錯性,儘可能多的使用try/catch塊來處理程式執行。使用.NET自定義Exception就能捕獲所有的異常信息,不需要特定異常的處理塊。將異常類作為方法參數或者返回值。在自定義異常中通過覆寫ToString方法報告異常信息,對這種操作不能掉以輕心,因為某些安全敏感信息有泄漏的可能。

異常是對程式介面隱含假設的一種違反。

從try/catch/finally說起:解析異常機制:try子句中通常包含可能導致異常的執行代碼,而try塊通常執行到引發異常或成功執行完成為止。catch子句包含了異常出現時的響應代碼,其執行規則是:一個try子句可以關聯零個或多個catch子句,CLR按照自上而下的順序搜索catch塊。catch子句包含的表達式,該表達式稱為異常篩選器,用於識別try塊引發的異常。如果篩選器識別該異常,則會執行該catch子句內的響應代碼;如果篩選器不接受該異常,則CLR將沿著調用堆棧向更高一層搜索,直到找到識別的篩選器為止,如果找不到則將導致一個未處理異常。異常篩選器,用於表示用戶可預料、可恢復的異常類,所有的異常類必須是System.Exception類型或其派生類,System.Excetpion類型是一切異常類型的基類。

程式中拋出該異常

推薦:http://www.cnblogs.com/roucheng/p/3521864.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本來打算按計劃做下去的,發現原來那個sprite雖然功能強大,但是對我想要做的東西來說,冗餘似乎有些多,決定自己寫一個。 之前做了一段時間的h5游戲,用的是panda.js,發現這個引擎封裝的還不錯,代碼很簡潔,決定借鑒著來寫自己的delphi game sprite。 這周成果: 1、設計了一個g ...
  • 性能測試排查定位問題,分析調優過程中,會遇到要分析gc日誌,人肉分析gc日誌有時比較困難,相關圖形化或命令行工具可以有效地幫助輔助分析。 Gc日誌參數 通過在tomcat啟動腳本中添加相關參數生成gc日誌 -verbose.gc開關可顯示GC的操作內容。打開它,可以顯示最忙和最空閑收集行為發生的時間 ...
  • 一、簡單裝飾器: 執行步驟: 1、@W1 執行W1,把自己裝飾的函數的函數名當做參數,即@W1 等價於W1(show)。 show()函數重新定義,即重新定義的show()函數等價於W1(show)返回值。 在重新定義的show()函數中去執行之前定義的函數。 二、帶參數裝飾器: 執行步驟: 1、執 ...
  • 採用gradle構建和發佈bboss版本及從maven中央庫下載bboss方法介紹 1.概述 bboss是國內最早採用gradle來構建和發佈版本的開源框架之一,那麼gradle是個什麼東東?以下公式可以大概表述一下意思: gradle=ant+maven 尤其是通過gretty插件直接可以在ecl ...
  • A peak element is an element that is greater than its neighbors. Given an input array where num[i] ≠ num[i+1], find a peak element and return its inde ...
  • 如果有介面,寫在介面方法上即可。滑鼠滑過方法名時時會顯示 如果沒有介面,寫在每個方法上方。 eclipse 分三步 ① 找到方法,並將游標移動至方法名的上方 ②/** ③回車 那,效果是醬紫 ...
  • 本來用之前也過的堆直接實現比較好,這裡我直接重新寫一了函數融入進去了 註釋部分的代碼,是用來進行哈夫曼編碼的,這種編碼方式就不需要使用三叉鏈的樹了(帶有parent指針的三叉樹) ...
  • 05年第一次接觸要做彩票項目的客戶,見面談了下,客戶給了一些各彩種各玩法的獎金文檔,並給了一個正在運營的彩票網站,客戶要求我們對照功能上評估工作量然後報價。 半個月後再次見面,通過評估後報價7W(當時客戶只要求做,重慶、天津、江西以及廣東、江西、山東11選、福彩3D、上海時時樂、北京快樂8)。敲定價 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...