日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET中委托写法的演变(上):委托与匿名方法

發布時間:2024/8/22 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET中委托写法的演变(上):委托与匿名方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

可能有一件事情需要說在前面,那就是:委托本身其實從來沒有改變過,改變的一直都是委托的“寫法”。因此更確切地說,改變的只是“編譯器”。而本文所有內容都用C#來實現,其實談得也都是C#編譯器本身——但是其實VB.NET也有變化啊。再由于.NET版本和C#版本的關系也是非常密切的,因此全文就使用.NET版本進行指代了。

.NET 1.x中委托的寫法

委托,如果不追究細節,從表面上來看我們可以將其通俗地理解為一個安全的“函數指針”。當然,這個函數指針其實也是一個對象,有自己的成員,也會封裝了被調用方的上下文等等。至于委托的定義和使用方式,則是這樣的:

public delegate int SomeDelegate(string arg1, bool arg2);public static int SomeMethod(string arg1, bool arg2) { return 0; }public class SomeClass {public int SomeMethod(string a1, bool a2) { return 0; }public event SomeDelegate SomeEvent; }static void Main(string[] args) {SomeClass someClass = new SomeClass();SomeDelegate someDelegate = new SomeDelegate(someClass.SomeMethod);someClass.SomeEvent += new SomeDelegate(SomeMethod); }

可見,在.NET 1.x中需要使用new DelegateType(...)的方式來創建一個委托對象。不過,作為委托對象內部的方法它既可以是實例方法,也可以是靜態方法。此外,方法只需要匹配委托類型的簽名和返回值即可,方法參數的名稱不會成為約束。

嗯,就是這么簡單。

.NET 2.0中委托的寫法

.NET中的委托引入了范型,且寫法略有簡化:

public delegate TResult MyFunc<T1, T2, TResult>(T1 a1, T2 a2);public static int SomeMethod(string a1, bool a2) { return 0; }static void Main(string[] args) {MyFunc<string, bool, int> myFunc = SomeMethod; }

在.NET 2.0中,new DelegateType已經可以省略,開發人員可以直接將方法賦值給一個委托對象的引用。當然,這個改進不值一提,.NET 2.0中委托寫法的關鍵在于引入了“匿名方法”:

public static void TestRequest(string url) {WebRequest request = HttpWebRequest.Create(url);request.BeginGetResponse(delegate(IAsyncResult ar){using (WebResponse response = request.EndGetResponse(ar)){Console.WriteLine("{0}: {1}", url, response.ContentLength);}},null); }

匿名方法,簡單地說就是內聯在方法內部的委托對象,它的關鍵便在于形成了一個閉包(委托執行時所需的上下文)。如上面的代碼中,BeginGetResponse的第一個參數(委托)可以直接使用TestRequest方法的參數url,以及方法內的“局部”變量request。如果沒有匿名函數這個特性的話,代碼寫起來就麻煩了,例如在.NET 1.x中您可能就必須這么寫:

展開 折疊public static void TestRequest(string url) {WebRequest request = HttpWebRequest.Create(url);object[] context = new object[] { url, request };request.BeginGetResponse(TestAsyncCallback, context); }public static void TestAsyncCallback(IAsyncResult ar) { object[] context = (object[])ar.AsyncState;string url = (string)context[0];WebRequest request = (WebRequest)context[1];using (WebResponse response = request.EndGetResponse(ar)){Console.WriteLine("{0}: {1}", url, response.ContentLength);} }

此時,我們往往會發現,開發人員需要花費大量的精力,為一小部分代碼維護一大段上下文。例如在這段代碼中,我們會將url和request對象塞入一個object數組中,在回調函數中再通過危險的Cast操作恢復數據。如果您希望“強類型”,那么只能為每個回調創建一個新的上下文對象,維護起來可能更加麻煩——要知道,在并行編程,異步調用越來越重要的今天,如果沒有匿名方法自動保留上下文的特性,開發人員會為這些“額外工作”疲于奔命的。

可能您會說,匿名方法的可讀性不佳,因為需要“內聯”。一個方法中內聯太多,維護成本就上去了,所以匿名方法并不推薦使用。我想說的是,您錯了。如果為了可維護性,要將方法獨立拆開,也可以利用匿名方法的優勢:

public static void TestRequest(string url) {WebRequest request = HttpWebRequest.Create(url);request.BeginGetResponse(delegate(IAsyncResult ar){TestAsyncCallback(ar, request, url);}, null); }public static void TestAsyncCallback(IAsyncResult ar, WebRequest request, string url) {using (WebResponse response = request.EndGetResponse(ar)){Console.WriteLine("{0}: {1}", url, response.ContentLength);} }

如果借助.NET 3.5中的Lambda表達式,代碼可以寫的更簡單易讀:

public static void TestRequest(string url) {WebRequest request = HttpWebRequest.Create(url);request.BeginGetResponse(ar => TestAsyncCallback(ar, request, url), null); }

匿名方法的作用

千萬不要小看匿名方法的作用,有些時候您認為它的作用僅限于上文描述,只是因為沒有在某些問題上踏前一步。例如,對于那些只需要“按需創建”,且要“線程安全”的對象,您會怎么做呢?沒錯,可以使用Double Check:

private object m_mutex = new object(); private bool m_initialized = false; private BigInstance m_instance = null;public BigInstance Instance {get{if (!this.m_initialized){lock (this.m_mutex){if (!this.m_initialized){this.m_instance = new BigInstance();this.m_initialized = true;}}}return this.m_instance;} }

嗯,做的很漂亮!那么……這樣的屬性再來一個,再來三個,再來五個呢?可能有些朋友就會開始大段地Copy & Paste,于是錯誤便難免了。這里有一件真人真事,以前某位同學在一堆這樣的代碼中迷茫了,說為什么用了這種方法,還是初始化了多次對象了?檢查了半天沒有看出問題來。最后發現,原因是訪問了錯誤的initialized變量(例如,在某個應該訪問artistInitialized的地方訪問了articleInitialized)。可惜,大段時間已經被浪費了——更糟的是,心情也隨之變差了。

其實,Copy & Paste很明顯沒有遵守DRY原則啊。為什么不把它們封裝在一處呢?例如:

展開 折疊public class Lazy<T> {public Lazy(Func<T> func){this.m_initialized = false;this.m_func = func;this.m_mutex = new object();}private Func<T> m_func;private bool m_initialized;private object m_mutex;private T m_value;public T Value{get{if (!this.m_initialized){lock (this.m_mutex){if (!this.m_initialized){this.m_value = this.m_func();this.m_func = null;this.m_initialized = true;}}}return this.m_value;}} }

于是,之前的代碼就可以簡化成這樣了:

private Lazy<BigInstance> m_lazyInstance =new Lazy<BigInstance>(delegate { return new BigInstance(); });public BigInstance Instance { get { return this.m_lazyInstance.Value; } }

還是太丑,上Lambda表達式!

private Lazy<BigInstance> m_lazyInstance =new Lazy<BigInstance>(() => new BigInstance()); public BigInstance Instance { get { return this.m_lazyInstance.Value; } }

如果沒有匿名方法,許多容易使用的編程模型和方式都難以開展。例如,我們就不會有CacheHelper,也不會有AsyncTaskDispatcher(上,下),也很難利用“延遲”所帶來的便利,更難以出現微軟并行擴展、CCR等優秀框架。可以這么說,如果您不善于使用委托,您如果不知道如何合適地使用匿名方法,您在不自知的情況下可能就已經編寫了大量額外的代碼了。

老趙平時的工作之一,便是為項目提供各種擴展API,可以讓程序員們更愉快地進行開發工作,得到更好的生產力,讓代碼變得更加美好。如今C#有了匿名方法、Lambda表達式、表達式樹、擴展方法等優秀的語言特性,真讓我有“如魚得水”的感覺。因此,我對于Java這樣不思進取的語言可以說深惡痛絕(Java朋友們趕快學習Scala吧)。在看閱讀大量Java開源項目代碼時,我常有這樣的感覺:“如果是C#的話,利用匿名方法,這個類不就可以不寫,那個類就可以省略……”。沒錯,為了保留回調函數的上下文而創建一些類,對于C#程序員來說,的確是一件有些不可思議的事情。

至于Lambda表達式以及其他話題,我們下次再說吧。

匿名方法的缺點

匿名方法的優勢在于自動形成閉包,而它的缺點也是讓程序員“不自覺”地創建了閉包,這會讓某些對象的生命周期加長。例如在一開始的TestRequest方法中,表面上看起來url是參數,request是局部變量,有些朋友可能會認為它們在方法退出后就已經準備回收了。不過因為形成了閉包,url和request已經“升級”為一個對象的域變量,它的生命周期延長了,延長至回調函數執行完畢。因此,一不注意可能就會產生一些莫名其妙的情況。

其實,這些都是“延遲”所帶來的陷阱,作為一個優秀的開發人員,除了知道某個東西的作用和優勢,也要知道它的問題,不是嗎?

轉載于:https://www.cnblogs.com/xiangshu/articles/2059572.html

總結

以上是生活随笔為你收集整理的.NET中委托写法的演变(上):委托与匿名方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲第一成人av | 久久国产精品精品国产 | 午夜在线观看免费视频 | 电家庭影院午夜 | 骚虎tv| 亲嘴脱内衣内裤 | 日韩亚洲视频 | jizz91| 国产又爽又黄免费视频 | 中文字幕在线网 | 黄色动漫在线免费观看 | 黄瓜视频在线免费观看 | 午夜九九 | 东北熟女一区二区三区 | 4388成人网 | 福利一区二区在线观看 | 日韩一区二区三 | 久久亚洲婷婷 | 色女人网站| 91亚洲精品在线观看 | 中文字幕av在线播放 | 日韩视频免费观看高清完整版 | 精品人妻一区二区三区四区不卡 | 午夜久久影院 | 国产黄色精品网站 | 国产精品美女久久久久av超清 | av在线免费观看网站 | 亚洲一一在线 | 电车痴汉在线观看 | 天天干影院 | 亚洲av中文无码乱人伦在线观看 | 成人黄色网址在线观看 | 蜜桃91丨九色丨蝌蚪91桃色 | 天堂在线中文 | 成人av免费网址 | 亚洲麻豆精品 | 天天看天天摸天天操 | 精品久久久久一区二区 | 美女搞黄在线观看 | 操你啦免费视频 | 欧美精品免费在线 | 国产v综合v亚洲欧美久久 | 国精产品乱码一区一区三区四区 | 久久久国产视频 | 亚洲成人福利视频 | 不卡av在线免费观看 | 香蕉久草| www.四虎.com| 毛片在线播放视频 | 亚洲私人影院 | 欧美韩国日本在线 | 天天干天天操天天插 | 理论在线视频 | 欧美熟妇另类久久久久久多毛 | 成人性生活毛片 | 国产永久精品大片wwwapp | 亚洲欧美成人一区 | 欧美sm极限捆绑bd | 黄色精品一区 | 欧美性色a | 色哟哟免费在线观看 | 麻豆免费在线观看视频 | 国产女厕一区二区三区在线视 | 九一成人网 | 国产午夜精品一区二区理论影院 | 一区二区不卡视频在线观看 | 老头老太做爰xxx视频 | 中文字幕亚洲一区 | 免费国产一级 | 日韩精品中文字幕一区二区三区 | 欧美性受黑人性爽 | 丰满孕妇性春猛交xx大陆 | 双腿张开被9个男人调教 | 69热在线| 中文字幕亚洲综合 | 国产毛片一区二区三区 | 日本男人的天堂 | 丁香婷婷综合网 | 毛片基地在线播放 | 动漫涩涩免费网站在线看 | 天天人人 | 亚洲区一区二区三区 | 欧美亚洲黄色片 | 手机看片福利视频 | 国产一区av在线 | 一区二区三区四区影院 | 用力插视频| 国产精品女同一区二区 | 91精品人妻一区二区三区果冻 | 日韩免费高清一区二区 | 韩国三级在线视频 | 欧美久久久久久久久中文字幕 | 中文字幕国产综合 | 中国大陆毛片 | 亚洲一级色| 韩国伦理片在线观看 | 涩涩的视频在线观看 | 91丨porny丨成人蝌蚪 | 打屁屁日本xxxxx变态 |