前言html
泛型並非C#語言一開始就帶有的特性,而是在FCL2.0以後實現的新功能。基於泛型,咱們得以將類型參數化,以便更大範圍地進行代碼複用。同時,它減小了泛型類及泛型方法中的轉型,確保了類型安全。委託自己是一種引用類型,它保存的也是託管堆中對象的引用,只不過這個引用比較特殊,它是對方法的引用。事件自己也是委託,它是委託組,C#中提供了關鍵字event來對事件進行特別區分。一旦咱們開始編寫稍微複雜的C#代碼,就確定離不開泛型、委託和事件。本章將針對這三個方面進行說明。算法
本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要學習記錄如下內容:安全
建議3五、使用default爲泛型類型指定初始值異步
建議3六、使用FCL中的委託聲明學習
建議3七、使用lambda表達式代替方法和匿名方法this
建議3五、使用default爲泛型類型指定初始值編碼
有些算法,好比泛型集合List<T>的Find算法,所查找的對象有可能會是值類型,也有多是引用類型。在這種算法內部,咱們經常會爲這些值類型變量或引用類型變量指定默認值。因而,問題來了:值類型變來那個的默認初始值是0值,而引用類型變量的默認初始值是null值,顯然,這會致使下面編譯出錯:spa
C#編譯器會阻止這樣的代碼經過編譯。要讓編譯器接收爲一個泛型類型參數指定一個初始值,最穩當的辦法就是使用default關鍵字。因此,在上面的代碼應該改成:線程
public T Func<T>() { T t = default(T); return t; }
這樣若是它在運行時碰到的T是一個整型,那麼運行時會爲其賦值0;若是T在運行時是一個Person這樣的引用類型,則會爲其賦null值。3d
建議3六、使用FCL中的委託聲明
要注意FCL中存在三類這樣的委託聲明,他們分別是:Action、Func、Predicate。尤爲是在他們的泛型版本出來之後,已經可以知足咱們在實際編碼過程當中的大部分須要。
這裏是以前一篇關於Action、Func、Predicate的有關介紹http://www.cnblogs.com/aehyok/p/3382291.html
除了Action、Func、Predicate外,FCL中還有用於標識特殊含義的委託聲明。如用於表示註冊事件方法的委託聲明:
public delegate void EventHandler(object sender,EventArgs e); public delegate void EnentHandler<TEventArgs>(object sender,TEventArgs e);
表示線程的委託聲明:
public delegate void ThreadStart(); public delegate void ParameterizedThreadStart(object obj);
表示異步回調的委託聲明:
public delegate void AsyncCallback(IAsyncResult ar);
在FCL中沒一類委託聲明都表明一類特殊的用途,雖然可使用本身的委託聲明來代替,可是這樣作不只沒有必要,並且會讓代碼失去簡潔性和標準型。在咱們實現本身的委託聲明前,應該首先查看MSDN,確信有必要以後才這樣作。
建議3七、使用lambda表達式代替方法和匿名方法
首先咱們使用Action和Func來作一個簡單的小例子,控制檯應用程序代碼以下所示:
第一個版本
class Program { static int Add(int i, int j) { return i + j; } static void Print(string message) { Console.WriteLine(message); } static void Main(string[] args) { Func<int, int, int> add = Add; Action<string> print = Print; print(add(4, 5).ToString()); Console.ReadLine(); } }
實際上要完成上面的功能,還有多種編碼方式,先來看一種最中規中矩的方式,同時也是最繁瑣的寫法:
第二個版本
class Program { static int Add(int i, int j) { return i + j; } static void Print(string message) { Console.WriteLine(message); } static void Main(string[] args) { Func<int, int, int> add = new Func<int,int,int>(Add); Action<string> print =new Action<string>(Print); print(add(4, 5).ToString()); Console.ReadLine(); } }
其實也就是將第一個版本稍做調整。從上面的寫法中也能夠看出:Add方法和Print方法實際上都只有一條語句,所以,使用匿名方法也許是一種更好的選擇:
第三個版本
static void Main(string[] args) { Func<int, int, int> add = new Func<int,int,int>(delegate(int i,int j) { return i+j; }); Action<string> print =new Action<string>(delegate(string message) { Console.WriteLine(message); }); print(add(4, 5).ToString()); Console.ReadLine(); }
使用匿名方法之後,咱們不須要在Main方法外部聲明兩個方法了,能夠直接在Main這個工做方法中完成全部的代碼編寫,並且不會影響代碼清晰性。實際上,全部代碼行數不超過3行的方法(條件是它不倍重用),咱們都建議採用這種方式來編寫。上面的版本繼續改進:
第四個版本
static void Main(string[] args) { Func<int, int, int> add = delegate(int i,int j) { return i+j; }; Action<string> print =delegate(string message) { Console.WriteLine(message); }; print(add(4, 5).ToString()); Console.ReadLine(); }
以上代碼看上去更簡化了,不過,最終極的改進是使用lambda表達式:
第五個版本
static void Main(string[] args) { Func<int, int, int> add = (x, y) => x + y; Action<string> print = (message) => Console.WriteLine(message); print(add(4, 5).ToString()); Console.ReadLine(); }
Lambda表達式操做符」=>「的左側是方法的參數,右側是方法體,其本質是匿名方法。實際上,通過編譯後Lambda表達式就是一個匿名方法。咱們應該在實際的編碼工做中熟練運用它,避免寫出繁瑣且不美觀的代碼。