C#中的拜托數據類型簡介。本站提示廣大學習愛好者:(C#中的拜托數據類型簡介)文章只能為提供參考,不一定能成為您想要的結果。以下是C#中的拜托數據類型簡介正文
甚麼是拜托?
拜托是一個類型平安的對象,它指向法式中另外一個今後會被挪用的辦法(或多個辦法)。淺顯的說,拜托是一個可以援用辦法的對象,當創立一個拜托,也就創立一個援用辦法的對象,進而便可以挪用誰人辦法,即拜托可以挪用它所指的辦法。
來看上面的例子,類deleMthod界說了3個辦法,add、minus和multi,他們都具有雷同的輸出參數列表(int x,int y)和輸入參數類型int,那末我們就說這三個辦法具有雷同的辦法簽名。開辟者可以籠統地用 int 某稱號(int x,int y) 的一品種型對辦法停止封裝,在c#中這類籠統的數據類型叫拜托,針對上述的幾個辦法我們可以界說拜托 : public delegate int Handler(int x ,int y),public 是一個拜訪潤飾符,delegate症結字表現這是一個拜托,int Hander(int x,int y)表現這個拜托的稱號。
class deleMethod { public int add(int x, int y) { return x + y; } public int minus(int x, int y) { return x - y; } public int multi(int x, int y) { return x * y; } }
怎樣應用拜托
應用拜托年夜體有四個步調:
•界說一個拜托,上節曾經說起。
•界說拜托辦法,上節deleMethod類中add、minus、multi都是拜托辦法,界說的目標就是為了應用它,講專業點就是為了辦法的挪用
•拜托變量及賦值,和類型一樣,在應用前須要對變量賦值。
•拜托變量的應用。
如何界說拜托變量,照樣接著下面的例子。我們曾經界說了一個拜托類型 public delegate int Handler(int x,int y),和c#語律例范一樣界說一個變量並賦值語法是:“類型名 變量名 = new 類型名(辦法);”,如上例
“Handler deleCall = new Handler(辦法名);“,在.net2.0後關於拜托的實例化可以簡化為” Handler deleCall = 辦法名;“。
拜托變量的應用,也就是對拜托辦法的挪用。其語法是”int result1 = deleCall(10,20);“或許應用拜托挪用辦法 Invoke,“int result2 = deleCall.Invoke(10,20);”。
詳細若何應用可以看看上面的示例:
class Program { public delegate int Handler(int x, int y); //---界說拜托的類型,可以將拜托算作一種特別的數據類型 static void Main(string[] args) { deleMethod dm = new deleMethod(); //---實例化包括拜托辦法的類型 Handler deleCall = new Handler(dm.add); //---界說拜托變量delCall,並出示化賦值 int result1 = deleCall(10, 20); //---實例辦法的挪用invoke Console.WriteLine("the add resutl is:{0}", result1); deleCall = dm.minus; int result2 = deleCall.Invoke(12, 6); Console.WriteLine("the minus result is:{0}", result2); Console.ReadLine(); } }
如上例所示,界說一個簡略的加、減功效如斯的龐雜,攪來攪去讓人頭,真是無語,難怪許多同伙談拜托色變暈。在現實應用的進程中,c#照樣有許多方法幫我們簡化代碼。
簡化拜托
預界說的泛型拜托
c#體系最多見的預界說的拜托類型有三種,Func<>拜托、Action<>拜托、Predicate<>拜托,Func<>拜托是一個有前往值的拜托,輸出參數可以多達16個;而Action<>拜托是一個沒有前往值的拜托,它的輸出參數也能夠多達16個;而Predicate<>是一個具有bool前往類型的拜托,它只運轉一個輸出參數。關於有上例的拜托類型,我們可使用預界說的拜托類型Fun<int,int,int>來取代,省去我們本身界說一個甚麼鬼器械 public delegate int Handler(int x,int y)類型,其代碼其實可以簡化為以下例所示:
namespace DelegateDemo1 { class Program { static void Main(string[] args) { deleMethod dm = new deleMethod(); Func<int, int, int> fun = dm.add; //---應用預界說的拜托類型Func<> int result4 = fun(8, 10); Func<int, int, int> fun1 = dm.minus; int result5 = fun1(12, 8); Console.WriteLine("預界說的拜托輸入{0},{1}", result4, result5); Console.ReadLine(); } } class deleMethod { public int add(int x, int y) { return x + y; } public int minus(int x, int y) { return x - y; } public int multi(int x, int y) { return x * y; } } }
我把拜托的辦法界說和拜托的挪用放在一路看,是否是比本來本身界說的一個拜托類型簡略便利一些?然則如許應用拜托照樣不怎樣清新,估量在現實運用中很少人會怎樣寫代碼,太不便利了。
匿名拜托
當拜托實例的挪用和拜托辦法的界說離開處置,碼農們在讀法式代碼的時刻須要往返的去找拜托辦法去婚配拜托變量,看看參數列表和前往值能否准確,如許的法式代碼的可讀性很差。其實c#照樣無方法讓我們簡化代碼:那就是匿名拜托,將辦法體直接在拜托的實例化時給出,之所以叫匿名拜托就是再界說拜托的時刻省略失落拜托的稱號,它的界說語法是delegate(參數1,參數2) 前面直接就給出辦法體,用年夜括號將辦法體括起。剛看起來比擬奇異,接觸多了也就習氣了,莫有方法只能去順應c#的語律例范。話說多了是水,還不如看代碼來得直接。
namespace DelegateDemo1 { class Program { static void Main(string[] args) { Func<int, int, int> fun = delegate(int x, int y) { return x + y; }; Func<int, int, int> fun1 = delegate(int x, int y) { return x - y; }; int result4 = fun(8, 10); int result5 = fun1(12, 8); Console.WriteLine("預界說的拜托輸入{0},{1}", result4, result5); Console.ReadLine(); } } }
看看是否是在本來的基本上年夜幅度削減了代碼量,腫麼辦,能否代碼量曾經削減到極致了?
lambda表達式
其實關於拜托的界說還可以進一步簡化,那就是應用lambda表達式,lambda表達式的界說是(參數列表)=>{辦法體},=>讀作goes to。lambda表達式對參數列表和辦法表達式的精簡到達極致,關於下面的例子,用λ表達式可以省略失落匿名拜托的症結字和參數類型,體系可以停止類型揣摸,不影響運轉,其簡化的代碼以下。對.net 1.0,2.0最傳統的拜托界說和應用,是一個偉大的簡化,它剔除一切過剩的語句到達極致。
namespace DelegateDemo1 { class Program { static void Main(string[] args) { Func<int, int, int> fun = (x, y) => x + y; Func<int, int, int> fun1 = (x, y) => x - y; int result4 = fun(8, 10); int result5 = fun1(12, 8); Console.WriteLine("預界說的拜托輸入{0},{1}", result4, result5); Console.ReadLine(); } } }
拜托鏈
後面講過,拜托在實質上依然是一個類,我們用delegate症結字聲明的一切拜托都繼續自System.MulticastDelegate。後者又是繼續自System.Delegate類,System.Delegate類則繼續自System.Object。一個拜托可以綁定若干雷同簽名的辦法構成一個拜托鏈,拜托鏈是一個拜托實例的聚集,它許可我們挪用這個聚集中的拜托實例所代表的一切辦法(關於有前往值的辦法,拜托鏈的前往值為鏈表中最初一個辦法的前往值),鄙人面的例子我們界說的拜托辦法都沒有前往值。我們可以用 GetInvocationList()辦法獲得拜托鏈。
class Program { static void Main(string[] args) { //Action 表現沒有前往值的一類辦法 Action<int, int> actionA = (x, y) => { Console.WriteLine("x是{0},y是{1},他們的平方和是{2}", x, y, x * x + y * y); }; actionA += (x, y) => { Console.WriteLine("x是{0},y是{1},他們的平方差是{2}", x, y, x * x - y * y); }; actionA(10, 5); foreach (var item in actionA.GetInvocationList()) Console.WriteLine(item.Method); Console.ReadLine(); } }
甚麼是事宜
常常看到一種界說是:事宜是一種特別的拜托,是對拜托的封裝。其實這類界說是很不嚴謹的。拜托是一種數據類型,然則事宜只是拜托的實例,不克不及算是一種數據類型,所以說事宜是一種特別的拜托是禁絕確的。假如如許界說:事宜是一種特別的拜托實例,是對拜托的封裝。那末在C#中事宜是若何界說並被應用的呢?其實事宜從界說到應用要經由四個階段。
•界說事宜依附的拜托,並界說事宜和激發事宜的辦法,該步調可以界說在事宜宣布器類中
•界說事宜所依附的事宜辦法,該步調可以界說在事宜定閱者類中
•假如有事宜參數,該步調可以界說在事宜參數類中
•注冊事宜並激發事宜,該步調普通寫在主法式中
普通來說在事宜界說進程中,各個辦法的定名沒有同一的尺度,但我們可以參考微軟在c#中的定名標准停止定名
建議事宜拜托定名為:事宜+EventHandler。假如有額定的參數傳遞需界說本身的參數類型,參數類型的定名標准 :事宜+EventHandler。好比,可以界說一個事宜拜托 public delegate void calcEventHandler(object sender,calcEventArgs e); 。
界說一個事宜變量如:public event calcEventHandler calc;
界說一個激發事宜的辦法如:public void onCalc(object sender,calcEventArgs e){}
建議辦法名為 on+事宜,就好像我們在開辟web法式時,綁定的事宜名有onClick,onLoad等一樣。
參考看上面的例子,懂得界說一個事宜的普通進程,假如不須要傳遞事宜的參數可以省去事宜參數類的界說,應用體系預界說的EventArgs便可以了。
/// <summary> /// 主法式類 /// </summary> class Program { static void Main(string[] args) { eventPublish myEvent = new eventPublish(); eventSubscription myMethod = new eventSubscription(); //綁定辦法 add 和 subtract,又稱為對事宜辦法的注冊 -=稱為對事宜辦法的刊出 myEvent.calc += myMethod.add; myEvent.calc += myMethod.substract; while (true) { try { Console.WriteLine("請輸出第一個整數數"); int numA = Convert.ToInt16(Console.ReadLine()); Console.WriteLine("請輸出第二個整數"); int numB = Convert.ToInt16(Console.ReadLine()); calcEventArgs e = new calcEventArgs(numA, numB); //在本例不須要sender參數,隨便傳遞了字符串"sender" myEvent.onCalc("sender", e); } catch (Exception ex) { Console.WriteLine("湧現毛病," + ex.Message); } } } } /// <summary> /// 界說一個事宜宣布器類 /// </summary> class eventPublish { //界說一個拜托類型,拜托名普通是 事宜變量名+EventHandler public delegate void calcEventHander(object sender,calcEventArgs e); //界說一個事宜變量,其變量名為calc public event calcEventHander calc; //封裝事宜,對外界說了激發事宜的辦法,界說的激發辦法名普通是 on+事宜變量名 public void onCalc(object sender, calcEventArgs e) { if (calc != null) calc(sender,e); } } /// <summary> /// 界說一個事宜定閱者類(事宜辦法類) /// </summary> class eventSubscription { public void add(object sender, calcEventArgs e) { Console.WriteLine("兩數相加等於{0}", e.X + e.Y ); } public void substract(object sender, calcEventArgs e) { Console.WriteLine("兩數相減等於{0}", e.X - e.Y); } } /// <summary> /// 界說一個事宜參數類 /// </summary> class calcEventArgs : EventArgs { private int _x; private int _y; public calcEventArgs(int x, int y) { this._x = x; this._y = y; } public int X { get { return _x; } } public int Y { get { return _y; } } }
我們將事宜是對拜托的封裝,假如用ILDAS反編譯可履行文件檢查中央代碼便可以異常清楚明了的看失事件運轉機制
如上圖所示,事宜calc,經.net運轉時編譯為中央說話後發生了一個private 的calc屬性,同時也主動生成了add_calc和remove_calc辦法,用於注冊和刊出定閱者辦法。由於事宜是被封裝的,雖然calc屬性是private,但在所以在宣布器類外部可以用 calc(sender,e)如許的辦法直接挪用;但在主法式中假如如許應用就會失足,只能經由過程onCalc辦法停止直接挪用。
跋文
本篇文章,一開端提出了甚麼是拜托的疑問,經由過程引入幾個辦法來說述拜托是甚麼以增強對拜托概念的懂得。第二部門講述了應用拜托的四個步調,並經由過程示例論述了這幾個步調。第三部門講述了拜托應用的簡化成績,經由過程應用泛型拜托簡化自界說拜托,經由過程應用匿名拜托可以簡化界說拜托辦法。匿名拜托是在界說拜托的時刻直接給出辦法體,經由過程應用lambda表達式的類型揣摸可進一步簡化拜托的應用。第四部門講述了拜托鏈,經由過程綁定辦法初始化拜托,並經由過程+=綁定更多的拜托辦法。第五部門講述了事宜的界說和應用的四個步調。固然拜托的應用場景還有許多,好比經由過程BeginInvoke和EndInvoke停止異步驟用,因不是本篇文章的重點,所以文章中沒有說起。
以上內容是小編給年夜家引見的C#中的拜托數據類型簡介,願望對年夜家有所贊助!