乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      面試中的委托

       雄Frank 2012-02-13

      4.3  委托(1)

      委托技術(shù)是.NET框架中的高級(jí)特性之一,也可以說(shuō)是.NET重要技術(shù)之一,是在大多數(shù)的技術(shù)筆試、面試中必定出現(xiàn)的部分。委托提供了安全的函數(shù)回調(diào)(CALL BACK)機(jī)制,成為程序員設(shè)計(jì)靈活簡(jiǎn)潔的.NET程序的重要方法之一。本章節(jié)將通過(guò)介紹委托概念和分析一些常見(jiàn)的委托技術(shù)題。

      面試題55  什么是委托

      .NET面試中經(jīng)常會(huì)被提問(wèn)什么是C#中的委托,面試官主要意圖是考察應(yīng)聘者對(duì).NET的幾個(gè)重要特性的了解。這樣的細(xì)節(jié)問(wèn)題往往讓程序員不能夠準(zhǔn)確地回答,讀者應(yīng)該在平時(shí)學(xué)習(xí)的過(guò)程中注意積累。

      【出現(xiàn)頻率】★★★★★

      【關(guān)鍵考點(diǎn)】

      委托(Delegate)

      委托的特點(diǎn)

      【考題分析】

      委托是一種引用類(lèi)型,它是函數(shù)指針的托管版本。在C#中,委托是一種可以把引用存儲(chǔ)為函數(shù)的類(lèi)型。委托可以引用實(shí)例和靜態(tài)方法,而函數(shù)指針只能引用靜態(tài)方法。委托的聲明非常類(lèi)似函數(shù),和函數(shù)不同的是委托不帶函數(shù)體,并且需要使用Delegate關(guān)鍵字。委托的聲明指定了一個(gè)函數(shù)簽名,其中包含參數(shù)列表和一個(gè)返回類(lèi)型。在定義了委托后,就可以聲明該委托類(lèi)型的變量,然后可以將這個(gè)變量初始化為與該委托有相同簽名的函數(shù)進(jìn)行引用,隨后可以使用委托變量調(diào)用該函數(shù)。

      注意:委托雖然與函數(shù)指針?lè)浅n?lèi)似,但卻不是指針。許多程序員把.NET中的委托理解為安全的函數(shù)指針,這樣的理解是比較牽強(qiáng)的,委托實(shí)現(xiàn)的功能和函數(shù)指針?lè)浅n?lèi)似的一點(diǎn)就是提供了程序回調(diào)機(jī)制。

      委托的內(nèi)部實(shí)現(xiàn)機(jī)制和函數(shù)指針在指向方法這一點(diǎn)上是完全相同的。委托是安全的,主要因?yàn)槲泻推渌械?NET成員一樣,均是一種類(lèi)型,都是System.Delegate的某個(gè)派生類(lèi)的一個(gè)對(duì)象。

      現(xiàn)在來(lái)分析一個(gè)具體的例子,示例代碼如下:

      1. using System;  
      2. namespace MyConsole  
      3. {  
      4.     class SimpleDelegate  
      5.     {  
      6.         //定義一個(gè)返回為double類(lèi)型的委托,這個(gè)委托有一個(gè)整型的輸入?yún)?shù)  
      7.         public delegate double Delegate_Prod(int a);  
      8.         static double fn_Prodvalues(int val1)  
      9.         {  
      10.             return val1 * val1;  
      11.         }  
      12.         static void Main(string[] args)  
      13.         {  
      14. Delegate_Prod delObj = new Delegate_Prod(fn_Prodvalues);  
      15.                                                 //聲明一個(gè)委托  
      16.             Console.Write("請(qǐng)輸入數(shù)字");  
      17.             int v1 = Int32.Parse(Console.ReadLine());  
        //輸入一個(gè)整型數(shù)值  
      18.             double res = delObj(v1);               
        //調(diào)用委托方法fn_Prodvalues  
      19.             Console.WriteLine("返回值:" + res);            //返回結(jié)果  
      20.             Console.ReadLine();  
      21.         }  
      22.     }  

      示例代碼中,首先通過(guò)public delegate double Delegate_Prod(int a)定義了一種名為Delegate_Prod的新類(lèi)型,這個(gè)類(lèi)型繼承自System.MulticastDelegate。它包含一個(gè)名為Invoke()的方法,該方法接收一個(gè)字符型的參數(shù)且沒(méi)有任何返回。這些步驟都是由C#編譯器自動(dòng)完成的。然后,聲明了一個(gè)Delegate_Prod的對(duì)象delObj,并且綁定到fn_Prodvalues這個(gè)靜態(tài)方法上。運(yùn)行結(jié)果如下:

      1. 請(qǐng)輸入數(shù)字9  
      2. 返回值: 81 

      注意:本質(zhì)上,委托的調(diào)用就是執(zhí)行了在定義委托時(shí)所生成的Invoke()方法。

      C#中的委托類(lèi)都繼承自System.Delegate類(lèi)型。委托類(lèi)型的聲明與方法簽名相似,有一個(gè)返回值和任意數(shù)目任意類(lèi)型的參數(shù)。委托是一種可用于封裝命名或匿名方法的引用類(lèi)型。委托類(lèi)似于函數(shù)指針,但是委托是類(lèi)型安全和可靠的。

      面試題56  C#中被委托的方法必須是靜態(tài)的嗎

      關(guān)于委托的方法是否必須是靜態(tài)方法這個(gè)考題,考察點(diǎn)非常明確。面試官一般希望了解應(yīng)聘者是不是僅僅了解如何定義和簡(jiǎn)單的使用委托,是否真正掌握理解委托的內(nèi)部原理。

      【出現(xiàn)頻率】★★★★★

      【關(guān)鍵考點(diǎn)】

      靜態(tài)方法與實(shí)例方法的區(qū)別

      分析委托的方法是否必須是靜態(tài)方法

      【考題分析】

      在分析這個(gè)問(wèn)題之前,先了解C#幾個(gè)基本的概念。在C#中最常見(jiàn)的方法就是靜態(tài)方法和實(shí)例方法,它們之間的區(qū)別如表4.1所示。

      表4.1  靜態(tài)方法和實(shí)例方法的區(qū)別

      態(tài)

      實(shí)

      Static關(guān)鍵字

      不需要static關(guān)鍵字

      類(lèi)名調(diào)用

      實(shí)例對(duì)象調(diào)用

      可以訪問(wèn)靜態(tài)成員

      可以直接訪問(wèn)靜態(tài)成員

      不可以直接訪問(wèn)實(shí)例成員,需要實(shí)例化

      可以直接訪問(wèn)靜態(tài)成員

      不能直接調(diào)用實(shí)例方法,需要實(shí)例化

      可以直接調(diào)用實(shí)例方法和靜態(tài)方法

      調(diào)用前初始化

      實(shí)例化時(shí)初始化

       

      如表4.1所示,在C#中靜態(tài)方法由關(guān)鍵字static來(lái)定義。靜態(tài)方法不需要實(shí)例化該對(duì)象,即可以通過(guò)類(lèi)名來(lái)訪問(wèn)對(duì)象。相應(yīng)地,在靜態(tài)方法中不能直接訪問(wèn)類(lèi)型中任何非靜態(tài)成員。而實(shí)例方法,則需要通過(guò)具體的實(shí)例對(duì)象來(lái)調(diào)用,并且可以訪問(wèn)實(shí)例對(duì)象中的任何成員對(duì)象。

      委托綁定實(shí)例方法的分析,依據(jù)C#實(shí)例方法的定義,當(dāng)一個(gè)實(shí)例方法被調(diào)用時(shí),需要通過(guò)實(shí)例對(duì)象來(lái)訪問(wèn),因此綁定實(shí)例方法到委托時(shí),必須同時(shí)讓委托得到該實(shí)例方法的實(shí)例對(duì)象的信息。這樣,.NET才能在委托被回調(diào)(CallBack)的時(shí)候成功地執(zhí)行該實(shí)例方法。Delegate.Target屬性是一個(gè)指向目標(biāo)實(shí)例的引用,當(dāng)綁定實(shí)例方法給委托時(shí),該參數(shù)會(huì)被設(shè)置為該方法所在類(lèi)型的一個(gè)實(shí)例對(duì)象。

      委托綁定靜態(tài)方法的分析。Delegate.Target屬性是一個(gè)指向目標(biāo)實(shí)例的引用,當(dāng)綁定一個(gè)靜態(tài)方法給委托時(shí),則該參數(shù)會(huì)被設(shè)置為null。

      注意:如果委托調(diào)用一個(gè)或多個(gè)實(shí)例方法,則此屬性返回調(diào)用列表中最后一個(gè)實(shí)例方法的目標(biāo)。

      【答案】

      通過(guò)上面的分析讀者可以清晰地判別,委托不僅能綁定靜態(tài)方法,同時(shí)也可綁定實(shí)例方法。當(dāng)綁定實(shí)例方法時(shí),Delegate.Target屬性將會(huì)設(shè)置成指向該實(shí)例方法所屬類(lèi)型的一個(gè)實(shí)例對(duì)象,當(dāng)綁定靜態(tài)方法時(shí),Delegate.Target屬性將會(huì)被設(shè)置成null。

       

      4.3  委托(2)

      面試題57  什么是多播委托

      每個(gè)委托都只包含一個(gè)方法調(diào)用,調(diào)用委托的次數(shù)與調(diào)用方法的次數(shù)相同。如果要調(diào)用多個(gè)方法,就需要多次顯式調(diào)用這個(gè)委托。當(dāng)然委托也可以包含多個(gè)方法,這種委托稱(chēng)為多播委托。下面將詳細(xì)分析這個(gè)問(wèn)題。

      【出現(xiàn)頻率】★★★★

      【關(guān)鍵考點(diǎn)】

      多播委托的基本概念

      System.MulticastDelegate 的特性

      【考題分析】

      在本章前文中,筆者已經(jīng)詳細(xì)地介紹了委托的基本概念。而所謂的多播委托,是指引用多個(gè)方法的委托,當(dāng)調(diào)用委托時(shí),它連續(xù)調(diào)用每個(gè)方法。在調(diào)用過(guò)程中,委托必須為同類(lèi)型,返回類(lèi)型也必須是void,且不能帶輸出參數(shù)(但可以帶引用參數(shù)),這樣才能將委托的單個(gè)實(shí)例合并為一個(gè)多播委托。除此之外,多番委托的聲明和實(shí)例化方法都和其他委托沒(méi)有什么不同?,F(xiàn)在來(lái)看一個(gè)實(shí)際的例子,示例代碼如下:

      1. using System;  
      2. namespace MyConsole  
      3. {  
      4.     class MulticastDelegate  
      5.     {  
      6.         //定義委托,接收一個(gè)字符型參數(shù)  
      7.         public delegate void hellokittyHander(string msg);  
      8.         private void hellokitty1(string msg)  
      9.                                     //定義一個(gè)簡(jiǎn)單
        的私有方法hellokitty1()  
      10.         {  
      11.             Console.WriteLine("hello kitty1" + msg);  
      12.         }  
      13.         private void hellokitty2(string msg)  
      14.                                     //定義一個(gè)簡(jiǎn)單
        的私有方法hellokitty2()  
      15.         {  
      16.             Console.WriteLine("hello kitty2" + msg);  
      17.         }  
      18.         private void hellokitty3(string msg)  
      19.                                     //定義一個(gè)簡(jiǎn)單的
        私有方法hellokitty3()  
      20.         {  
      21.             Console.WriteLine("hello kitty3" + msg);  
      22.         }  
      23.         static void Main(string[] args)  
      24.         {  
      25.             MulticastDelegate SimpleDelegate = new
         MulticastDelegate();  
      26.             //聲明一個(gè)委托變量,并綁定第一個(gè)方法  
      27.             hellokittyHander hellokitty = new 
        hellokittyHander(SimpleDele-  
      28.             gate.hellokitty1);  
      29. hellokitty += new hellokittyHander(SimpleDelegate.hellokitty2);  
      30.                             //綁定第二個(gè)方法  
      31. hellokitty += new hellokittyHander(SimpleDelegate.hellokitty3);  
      32.                             //綁定第三個(gè)方法  
      33.             //刪除已經(jīng)調(diào)用委托方法  
      34.             hellokitty -new hellokittyHander
        (SimpleDelegate.hellokitty2);  
      35.             if (hellokitty != null)  
      36.                 hellokitty("這是一個(gè)委托demo");  
      37.             Console.ReadLine();  
      38.         }  
      39.     }  

      簡(jiǎn)單分析這個(gè)例子,示例代碼中首先定義了一個(gè)帶string參數(shù)無(wú)返回的委托hellokittyHander,在Main()函數(shù)中聲明了一個(gè)hellokittyHander的委托變量hellokitty,并綁定了第一個(gè)方法void hellokitty1(string msg)。然后,通過(guò)hellokitty += new new hellokittyHander(SimpleDelegate.hellokitty1)初始化了第二個(gè)委托,并且綁定了void hellokitty2(string msg) ,同時(shí)把第二個(gè)委托掛在第一個(gè)委托之后。緊接著,掛上第三個(gè)委托并綁定到 void hellokitty3(string msg)。這是一種比較簡(jiǎn)單明了的寫(xiě)法,在開(kāi)發(fā)ASP.NET 或者Windows應(yīng)用程序時(shí),當(dāng)一個(gè)按鈕事件被添加時(shí),Visual Studio就會(huì)為程序生成類(lèi)似的代碼。

      代碼運(yùn)行結(jié)果如下:

      1. hello kitty1 這是一個(gè)委托demo  
      2. hello kitty3 這是一個(gè)委托demo 

      在這里讀者可能會(huì)對(duì)這個(gè)輸出的代碼產(chǎn)生困惑,為什么hello kitty2沒(méi)有被輸出。事實(shí)上細(xì)心的讀者會(huì)發(fā)現(xiàn)在上面的程序中有一句取消綁定的事件,代碼如下:

      1. //刪除已經(jīng)調(diào)用委托方法  
      2. hellokitty -new hellokittyHander
        (SimpleDelegate.hellokitty2); 

      注意:多播委托是指一個(gè)委托的鏈表,而不是指另一類(lèi)特殊的委托。當(dāng)執(zhí)行鏈上的一個(gè)方法,后續(xù)委托方法將會(huì)依次被執(zhí)行。System.MulticastDelegate定義了對(duì)多播委托的支持。

      【答案】

      多播委托是指一個(gè)由委托串成的鏈表,當(dāng)鏈表上的一個(gè)委托被回調(diào)時(shí),所有鏈表上該委托的后續(xù)委托將會(huì)被順序執(zhí)行。但要注意,多播委托必須是同類(lèi)型的,返回類(lèi)型必須是void,并且不能帶輸出參數(shù)(但可以帶引用參數(shù))。

      面試題58  列舉一個(gè)C#中的委托應(yīng)用

      列舉C#中的委托應(yīng)用是一個(gè)比較抽象的問(wèn)題,面試官旨在考察應(yīng)聘者對(duì)委托的使用經(jīng)驗(yàn)和設(shè)計(jì)能力。為了解釋這一問(wèn)題,本小節(jié)將帶領(lǐng)讀者實(shí)際體會(huì)一個(gè)具體的例子。為了能夠熟悉地運(yùn)用委托,讀者仍然需要在實(shí)際工作學(xué)習(xí)中不斷地積累經(jīng)驗(yàn)。

      【出現(xiàn)頻率】★★★★

      【關(guān)鍵考點(diǎn)】

      委托的設(shè)計(jì)

      委托的應(yīng)用

      【考題分析】

      排序系統(tǒng)在大多數(shù)系統(tǒng)中都有所應(yīng)用,在本小節(jié)中,筆者將舉一個(gè)學(xué)生成績(jī)排序的例子來(lái)說(shuō)明委托的實(shí)際應(yīng)用。下列代碼展示了這個(gè)學(xué)生成績(jī)排序系統(tǒng)的簡(jiǎn)單實(shí)現(xiàn)方式。

      示例中定義了學(xué)生類(lèi)型的基本成員、構(gòu)造方法,在私有構(gòu)造方法中,為學(xué)生排序委托定義了默認(rèn)的邏輯,示例代碼如下:

      1. //學(xué)生類(lèi)  
      2. class Student  
      3. {  
      4. private string name;                        //姓名字段  
      5. private decimal score;                      //成績(jī)字段  
      6. public Student(string name,decimal score)   //構(gòu)造函數(shù)、參數(shù)姓名和成績(jī)  
      7. {  
      8.     this.name = name;  
      9.     this.score = score;  
      10. }  
      11. ///比較方法  
      12. ///<param name="lhs">左側(cè)學(xué)生對(duì)象</param> 
      13. ///<param name="rhs">右側(cè)學(xué)生對(duì)象</param> 
      14. ///<returns>右側(cè)學(xué)生對(duì)象的成績(jī)高則返回true</returns> 
      15. public static bool RhsIsGreater(object lhs, object rhs)  
      16. {  
      17.     Student studentL = (Student)lhs;  
      18.     Student studentR = (Student)rhs;  
      19.     return (studentR.score > studentL.score) ? true : false;  
      20. }  
      21. ///<returns>預(yù)定義格式的輸出</returns> 
      22. //重寫(xiě)ToString方法,可以使得輸出更加清晰,輸出預(yù)定義格式  
      23. public override string ToString()  
      24. {  
      25.     return string.Format(name + " : " + score);  
      26. }  
      27. 4.3  委托(3)

        定義成績(jī)排序的委托方法,并將這個(gè)方法添加到委托對(duì)象之中。以下示例代碼使用冒泡法排序法對(duì)數(shù)組進(jìn)行排序。

        1. ///<summary> 
        2. ///排序類(lèi),方法Sort為靜態(tài)方法,使用冒泡法  
        3. ///</summary> 
        4. class ScoreSort  
        5. {  
        6.     ///<summary> 
        7.     ///冒泡法排序  
        8.     ///</summary> 
        9.     ///<param name="sortArray">要進(jìn)行排序的數(shù)組</param> 
        10.     ///<param name="Method">排序的方法</param> 
        11.     static public void Sort(object[] sortArray, CompareOp Method)  
        12.     {  
        13.         //外圍第一次循環(huán)  
        14.         for (int i = 0; i < sortArray.Length; i++)  
        15.         {  
        16.             //第二次循環(huán)  
        17.             for (int j = i + 1; j < sortArray.Length; j++)  
        18.             {  
        19.                 //比較大小并交換  
        20.                 if (Method(sortArray[j], sortArray[i]))  
        21.                 {  
        22.                         object temp = sortArray[i];  
        23.                     sortArray[i] = sortArray[j];  
        24.                     sortArray[j] = temp;  
        25.                 }  
        26.             }  
        27.         }  
        28.     }  

        最后可以編寫(xiě)測(cè)試代碼,來(lái)測(cè)試學(xué)生排序的功能,示例代碼如下:

        1. using System;  
        2. using System.Collections.Generic;  
        3. using System.Text;  
        4. namespace MyConsole  
        5. {  
        6.     class StudentSort  
        7.     {  
        8.     //定義一個(gè)委托  
        9.     delegate bool CompareOp(object lhs, object rhs);  
        10.         static void Main(string[] args)  
        11.         {  
        12.             //初始化一個(gè)學(xué)生數(shù)組  
        13.             Student[] students =  
        14.             {  
        15.                 new Student("Zhang", 86),  
        16.                 new Student("Li", 75),  
        17.                 new Student("Wang", 93),  
        18.                 new Student("Zhao", 68),  
        19.                 new Student("Liu", 53),  
        20.                 new Student("Jia", 100),  
        21.                 new Student("Pan", 83)  
        22.             };  
        23.             //使用RhsIsGreater方法進(jìn)行比較,并用Sort方法排序  
        24.             CompareOp studentCompareOp = new CompareOp(Student.RhsIsGrea-  
        25.             ter);  
        26.             ScoreSort.Sort(students, studentCompareOp);  
        27.             //循環(huán)輸出所有學(xué)生的已排序成績(jī)  
        28.             for (int i = 0; i < students.Length; i++)  
        29.             {  
        30.                 Console.WriteLine(students[i].ToString());  
        31.             }  
        32.             Console.ReadLine();  
        33.         }  
        34.     }  

        下面是示例代碼執(zhí)行后的輸出:

        1. Liu: 53  
        2. Zhao: 68  
        3. Li: 75  
        4. Pan: 83  
        5. Zhang: 86  
        6. Wang: 93  
        7. Jia: 100 

        【答案】

        委托的應(yīng)用環(huán)境通常是任務(wù)的執(zhí)行者把細(xì)節(jié)任務(wù)進(jìn)行再次分配,執(zhí)行者明確地知道被執(zhí)行的工作是什么,而且可以把這些執(zhí)行細(xì)節(jié)委托給其他組件、方法或者程序集。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多