【轉】編寫高品質代碼改善C#程式的157個建議——建議39:瞭解委託的實質

來源:互聯網
上載者:User

標籤:ide   點對點   ldl   類型   資料   ati   瞭解   傳輸過程   progress   

 

建議39:瞭解委託的實質

理解C#中的委託需要把握兩個要點:

1)委託是方法指標。

2)委託是一個類,當對其進行執行個體化的時候,要將引用方法作為它的構造方法的參數。

設想這樣一個情境:在點對點檔案傳輸過程當中,我們要設計一個檔案傳輸類,該傳輸類起碼要滿足下面幾項功能:

  • 傳輸問題件;
  • 按照百分制通知傳輸進度;
  • 傳輸類能夠同時被控制台程式和WinForm應用程式使用。

由於要讓通知本身能夠被控制台程式和WinFrom應用程式使用,因此設計這個檔案傳輸類在進行進度通知時,就不能顯示調用:

Console.WriteLine("當前進度:"+fileProgress);

或者

this.progressText.Text = "當前進度:" + fileProgress;

理想情況下是,在需要通知的地方,全部將其置換成一個方法的指標,由調用者來決定該方法完成什麼功能。這個方法指標在C#中就是委託。可以像下面那樣聲明委託:

public delegate void FileUploadedHandler(int progress);

這個檔案傳輸類可以寫成這樣:

    class FileUploader    {        public delegate void FileUploadedHandler(int progress);        public FileUploadedHandler FileUploaded;                public void Upload()        {            int fileProgress = 100;            while (fileProgress > 0)            {                //傳輸代碼,省略                fileProgress--;                if (FileUploaded != null)                {                    FileUploaded(fileProgress);                }            }        }    }

調用者在調用這個檔案傳輸類的時候,應該同時為FileUploaded賦值,賦值過程中也就是將自身所具有的和委託聲明相同的聲明方法賦值給FileUploaded。這樣,類型FileUploader在執行到下面的代碼時,就是執行調用者自身的方法

 FileUploaded(fileProgress);

理解了“委託是方法指標”這一點後,在了理解“委託是一個類”。

查看下面這句話:

public delegate void FileUploadedHandler(int progress);

它的IL代碼為:

.class auto ansi sealed nested public FileUploadedHandler    extends [mscorlib]System.MulticastDelegate{    .method public hidebysig specialname rtspecialname instance void .ctor(object ‘object‘, native int ‘method‘) runtime managed    {    }    .method public hidebysig newslot virtual instance class [mscorlib]System.IAsyncResult BeginInvoke(int32 progress, class [mscorlib]System.AsyncCallback callback, object ‘object‘) runtime managed    {    }    .method public hidebysig newslot virtual instance void EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed    {    }    .method public hidebysig newslot virtual instance void Invoke(int32 progress) runtime managed    {    }}

調用委託方法:

FileUploaded(fileProgress);

其實是調用:

FileUploaded.Invok(fileProgress);

可以查看Upload方法的IL代碼:

.method public hidebysig instance void Upload() cil managed{    .maxstack 2    .locals init (        [0] int32 fileProgress,        [1] bool CS$4$0000)    L_0000: nop     L_0001: ldc.i4.s 100    L_0003: stloc.0     L_0004: br.s L_0028    L_0006: nop     L_0007: ldloc.0     L_0008: ldc.i4.1     L_0009: sub     L_000a: stloc.0     L_000b: ldarg.0     L_000c: ldfld class MyTest.FileUploader/FileUploadedHandler MyTest.FileUploader::FileUploaded    L_0011: ldnull     L_0012: ceq     L_0014: stloc.1     L_0015: ldloc.1     L_0016: brtrue.s L_0027    L_0018: nop     L_0019: ldarg.0     L_001a: ldfld class MyTest.FileUploader/FileUploadedHandler MyTest.FileUploader::FileUploaded    L_001f: ldloc.0     L_0020: callvirt instance void MyTest.FileUploader/FileUploadedHandler::Invoke(int32)    L_0025: nop     L_0026: nop     L_0027: nop     L_0028: ldloc.0     L_0029: ldc.i4.0     L_002a: cgt     L_002c: stloc.1     L_002d: ldloc.1     L_002e: brtrue.s L_0006    L_0030: ret }

可以看到L_0020處調用Invoke方法。

 

一句話:委託是一種資料類型,它用來傳遞方法。

 

轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技

【轉】編寫高品質代碼改善C#程式的157個建議——建議39:瞭解委託的實質

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.