等待著元宵節的到來,過完元宵,這個年也算是過完了,也得開始出去掙錢了,過年回家感覺每個人都覺得很牛,只有自己太渣,為了避免年底再出現這樣尷尬的局面,還是需要努力幹活。爭取當上CEO,贏取白富美,走上人生巔峰。(生活需要幻想,也需要面對現實,努力獲取一個向上的心態,比起擁有財富要更加的難得。) 對於現 ...
等待著元宵節的到來,過完元宵,這個年也算是過完了,也得開始出去掙錢了,過年回家感覺每個人都覺得很牛,只有自己太渣,為了避免年底再出現這樣尷尬的局面,還是需要努力幹活。爭取當上CEO,贏取白富美,走上人生巔峰。(生活需要幻想,也需要面對現實,努力獲取一個向上的心態,比起擁有財富要更加的難得。)
對於現在還在聊QQ和看博客的同志們,我只想借用上圖問一句“你們不上班麽?...哈哈哈...”。好了,不扯淡了,開始我們今天的主題。
C#的類型中,我們知道最多的就是靜態類,對於靜態類的一些特性在這裡就不做介紹了,因為對於一個.NET開發者來說,靜態類的一些特性應該是有一定的掌握,並且在項目中應用的也是非常多。現在需要介紹的是另一種類型,那就是“分部類型”,對於“分部類型”的瞭解,很多人估計也就是知道而已,接下來就讓我們一起來學習一個“分部類型”這一C#的語言特點。
一.C#分部類型和分部方法解析:
1.分部類型概述:
學習“分部類型”,我們還是先來瞭解一下什麼叫做“分部類型”。分部類型是指可以在多個源文件中為一個類型編寫代碼。對於分部類型的使用場景,使用最多的地方是部分代碼是自動生成,而其他部分的代碼為手寫的類型。“分部類型”是由C#2.0時引入的。在繼承鏈上存在一個不必要的鏈接,會引發某些問題或降低封裝型。
我們現在對於分部類型的定義有一個大致的瞭解,以及對分部類型的應用場景也有一個初步的瞭解,接下來我們來看一下如何創建分部類型和分部類型的使用方法。
2.分部類型的創建和使用方法:
如果需要創建分部類型,我們只需要在涉及的每個文件的類型的聲明部分添加一個上下文關鍵字partial。對於分部類型,編譯器在編譯之前就把所有的文件合併在一起了。在一個文件中代碼可以調用另外一個文件中的代碼。有如下代碼:
SegmentType1.cs:
partial class SegmentType { private void Add() { Update(); } private void Delete() { } }
SegmentType2.cs
partial class SegmentType { private void Update() { Delete(); } }
以上是對分部類型做了一個簡單的申明和應用,這兩個.CS文件在編譯器編譯之前就已經合併在一起了。對於分部類型不能在一個文件中編寫成員的一半代碼,而把另外一半代碼放到另外一個文件中,必須保證每個獨立的成員必須完整地位於它所處的文件中。如下代碼:
SegmentType1.cs:
partial class SegmentType { private void Add(string fileName) { FileStream fs = null; try { fs = File.Create(fileName); } } }
SegmentType2.cs
partial class SegmentType { private void Update() { Add(); catch (ArgumentException arex) { throw arex; } finally { if (fs != null) { fs.Close(); fs.Dispose(); } } } }
上面演示的做法是無法通過編譯的。
對於類型的聲明還有一些限制,那就是聲明必須要相互相容,任何文件都能指定要實現的介面和基類型,以及類型參數的約束。如果多個文件都設定了基類型,那麼它們必須是相同的,並且如果多個文件都設定了類型參數約束,那麼約束必須是一致的。有如下代碼實例:
SegmentType1.cs:
//介面約束:IEquatable<string>; //where TFirst:class :和類型參數約束 partial class SegmentType<TFirst,TSecond>:IEquatable<string> where TFirst:class { //實現IEquatable<string>介面方法 public bool Equals(string other) { return false; } }
SegmentType2.cs
//指定基類:EventArgs //指定介面:IDisposable partial class SegmentType<TFirst, TSecond> :EventArgs,IDisposable { //實現方法 public void Dispose() { } }
以上的介面和基類約束中,也可以使用如下方法:
SegmentType1.cs:
//介面約束:IEquatable<string>; //where TFirst:class :和類型參數約束 partial class SegmentType<TFirst,TSecond>:IEquatable<string> where TFirst:class { //實現方法 public void Dispose() { } }
SegmentType2.cs
//指定基類:EventArgs //指定介面:IDisposable partial class SegmentType<TFirst, TSecond> :EventArgs,IDisposable { //實現IEquatable<string>介面方法 public bool Equals(string other) { return false; } }
對於介面和基類型約束可以進行交換,基於這種特性,可以將指定的介面與實現分離,將為不同類型生成相同的簽名的方法封裝到一個介面中。無法在聲明類型時指定其實現了該介面。
以上是主要講解了分部類型的創建和使用方式,接下來我們再來瞭解一下分部方法的相關知識。
3.分部方法解析:
對於分部方法的相關概念,在前面介紹分部類型時已經做了介紹,分部方法的創建和使用與分部類型類似。分部方法有一個特點:任何對未實現的分部方法的調用,都會被編譯器移除。
分部方法的聲明與抽象方法的申明類似,只需要使用partial修飾符提供簽名而無須任何實現。實現也需要partial修飾符進行修飾。有如下代碼:
SegmentType1.cs:
partial class SegmentType { public SegmentType() { SegmentTypeStart(); Console.WriteLine("分部方法解析..."); SegmentTypeEnd(); } partial void SegmentTypeStart(); partial void SegmentTypeEnd(); }
SegmentType2.cs
partial class SegmentType { partial void SegmentTypeStart() { Console.WriteLine("分部方法開始..."); } }
在分部方法中,由於方法可能不存在,所以分部方法返回類型必須聲明為void,且不能獲取out參數。分部方法必須是私有的,但是是靜態的或是泛型。
二.C#分部類型和分部方法的特點:
上面介紹了分部類型和分部方法的定義、創建和使用方式,在這裡主要介紹一下分部方法和分部類型的特點。分部類型主要連接設計器和其他代碼生成器。利用分部類型模型,代碼生成器可以擁有自由的操作文件,或者只要它願意可以每次都重寫整個文件。
某些代碼生成器還可以選擇不生成任何C#文件,而是等到構建進行的時候再生成。代碼生成器的應用比較的廣泛,比如Web伺服器代理、ORM工具生成配置文件等等。對於在ORM工具的應用有如下圖:
分部類型在其他方面也有比較多的使用,分部類型可以輔助我們進行重構。(重構的第一步就是將比較大的類型分成較小的類,很多的關聯的內容首先就可以分割為在兩個或多個文件上存放的分部類型。)
分部類型也可以幫助我們進單元測試。
分部方法能在手動創建的文件中指定某種行為,併在自動生成的文件中使用該行為。
三.C#分部類型實例:
分部類型和分部方法是一個語言特性,在這裡給出一個使用了分部類型的項目。https://github.com/fiidau/Phasing-Utility
四.總結:
對於分部類型和分部方法的介紹還有很多,在本文中只是做了一個簡單的介紹,分佈類型的使用也是比較的廣泛,可以極大的提升我們的代碼質量。希望本文對大家有所幫助。