第 76 講:C# 2 之方法組轉(zhuǎn)委托
新年快樂(lè)啊各位!現(xiàn)在是 1 月 1 日,還有兩個(gè)月,這教程都更了一年了。新的一年,希望各位再接再厲!
本節(jié)內(nèi)容也跟委托類(lèi)型有關(guān)??梢灾?,委托在 C# 里的重要性。
Part 1 從另一個(gè)維度簡(jiǎn)化委托類(lèi)型實(shí)例化
前文我們介紹了匿名函數(shù)的機(jī)制,它允許我們實(shí)例化一個(gè)自己額外定義的方法,并允許捕獲變量的機(jī)制。那么,假如我們的方法本身就存在呢?
考慮一點(diǎn)。我要遍歷序列,并執(zhí)行指定的操作來(lái)使用每個(gè)序列里的元素。比如:
Action<T>
是吧。很容易理解,就是把數(shù)據(jù)得到后,直接調(diào)用 Console.WriteLine
方法去輸出。
可是,有必要這么寫(xiě)嗎?你看看,我下面這樣的寫(xiě)法對(duì)不對(duì):
PrintList
方法的時(shí)候,參數(shù) printer
綁定了這個(gè)方法就會(huì)自動(dòng)去執(zhí)行它。所以,這么寫(xiě)也是沒(méi)錯(cuò)的語(yǔ)法。
順帶一提,這里的
Console.WriteLine
方法,你可以仔細(xì)看看這個(gè) API。它有很多重載,正是因?yàn)槿绱耍?/span>Console.WriteLine
這個(gè)寫(xiě)法才叫做方法組。但是,因?yàn)槲覀儗?shí)例化的類(lèi)型是Action<int>
類(lèi)型,因此對(duì)應(yīng)的簽名是void Action<int>(int)
一樣的東西。而Console.WriteLine
方法組里包含傳入int
不返回值的重載版本,因此這樣實(shí)例化是正確的。
而這樣的實(shí)例化語(yǔ)法 new Action<int>(Console.WriteLine)
,因?yàn)閰?shù)類(lèi)型是我們已知的,因此 C# 2 簡(jiǎn)化了此語(yǔ)法,不再要求你必須 new Action<int>
了:
是的??梢园l(fā)現(xiàn)這樣的寫(xiě)法簡(jiǎn)單了不少。這種語(yǔ)法特性叫做方法組自動(dòng)轉(zhuǎn)換為委托類(lèi)型,簡(jiǎn)稱(chēng)方法組轉(zhuǎn)換(Method Group Conversion),因?yàn)榉椒ńM一般也就只能用在委托里,所以“方法組轉(zhuǎn)換為委托”的“為委托”不用說(shuō),都知道是轉(zhuǎn)換成委托類(lèi)型實(shí)例的。
當(dāng)然,這種語(yǔ)法不一定非得用于參數(shù),也可以是委托類(lèi)型的變量定義過(guò)程:
等等。
Part 2 委托實(shí)例動(dòng)詞化
好吧,這個(gè)說(shuō)法確實(shí)唬到人了。實(shí)際上就是一個(gè)很簡(jiǎn)單的語(yǔ)法特性:委托類(lèi)型實(shí)例.Invoke(參數(shù))
可以簡(jiǎn)寫(xiě)成 委托類(lèi)型實(shí)例(參數(shù))
。舉個(gè)例子,我原來(lái)調(diào)用委托實(shí)例,可以這么寫(xiě)代碼:
printer.Invoke(element)
是最基本的調(diào)用形式,對(duì)吧。不過(guò),我們總是對(duì)委托類(lèi)型的實(shí)例使用 .Invoke
是的。我們直接將委托類(lèi)型的實(shí)例拿來(lái)執(zhí)行,這樣它和 .Invoke
的完整寫(xiě)法是沒(méi)有任何執(zhí)行和效率上的區(qū)別的,唯一的差別只是語(yǔ)法少了這么一個(gè) .Invoke
部分。這個(gè)語(yǔ)法特性叫做動(dòng)詞化(Verbize)。為啥要叫“動(dòng)詞化”?因?yàn)?,我們?cè)谡{(diào)用執(zhí)行一個(gè)方法的過(guò)程,它就好比是在完成一件事情,那么它就等于說(shuō)是在做某事。這不就是動(dòng)詞的工作嗎?而我們寫(xiě)上小括號(hào)就意味著,我們調(diào)用了方法,于是就相當(dāng)于是在執(zhí)行這個(gè)動(dòng)作。那么,給委托實(shí)例后加上參數(shù)表列就等于是在執(zhí)行委托實(shí)例,那么它就等于是在將一個(gè)實(shí)例(名詞)直接當(dāng)成動(dòng)詞用了。所以,我們把這種現(xiàn)象叫動(dòng)詞化。
不過(guò),這么寫(xiě)就需要你額外注意和小心了。委托類(lèi)型的實(shí)例是一個(gè)執(zhí)行的方法列表,只是我們總是只給這個(gè)方法列表里傳入一個(gè)方法組而已。實(shí)際上我們學(xué)過(guò)委托類(lèi)型,都知道委托和委托之間是可以使用加減法運(yùn)算的,它可以往整個(gè)委托的回調(diào)函數(shù)列表里增刪執(zhí)行的方法。那么,a()
的過(guò)程,如果 a
是委托類(lèi)型的實(shí)例,那么 a
就好比是啟動(dòng)了逐方法調(diào)用的機(jī)制;但對(duì)于 a
如果是普通方法而言,就僅僅是調(diào)用當(dāng)前方法了。也就是說(shuō),從寫(xiě)法上就不能區(qū)別它是委托類(lèi)型實(shí)例還是一個(gè)普通方法的調(diào)用了。
Part 3 沒(méi)了?
是的,沒(méi)了。這個(gè)語(yǔ)言特性是從另外一個(gè)維度簡(jiǎn)化委托類(lèi)型實(shí)例化的格式,因此也沒(méi)有必須要單獨(dú)去提及的點(diǎn)。