C#世界中的委托

来源:http://www.cnblogs.com/Helius/archive/2016/04/07/5363169.html
-Advertisement-
Play Games

委托是C#最重要的特性之一,C#後面的所有特性基本都是建立在委托的基礎上的。 1、C#委托是什麼? 可以把C#的委托理解為函數的一個包裝,它使得C#中的函數可以作為參數來被傳遞。如果你學過C++,可以理解為相當於上面的函數指針。 委托的定義和方法的定義類似,只是在定義的前面多了一個delegate關 ...


委托是C#最重要的特性之一,C#後面的所有特性基本都是建立在委托的基礎上的。

1、C#委托是什麼?

可以把C#的委托理解為函數的一個包裝,它使得C#中的函數可以作為參數來被傳遞。如果你學過C++,可以理解為相當於上面的函數指針。

委托的定義和方法的定義類似,只是在定義的前面多了一個delegate關鍵字。下麵就是一個委托的例子:

public delegate void MyDelegate(int para1,string para2);

委托能包裝的方法是有一定限制的,例如能被前面的委托類型MyDelegate包裝的方法需要滿足以下條件:

(1)方法的返回類型必須為void;

(2)方法必須有兩個參數,並且第一個參數應為int類型,第二個參數為String類型。

比如:public vodi MyMethod(int a,string b){}

總結一下可以得出:被委托包裝的方法必須滿足方法的簽名必須與委托一致,並且返回類型也是要一致的。(方法簽名:包括參數的個數、類型和順序;返回類型不包含在放哪廣發簽名里)。

 

2、委托的使用

使用的方式當然是Show出代碼來解釋最清楚了。

class Program
{
  //1、使用delegate關鍵字來定義一個委托類型
  delegate void MyDelegate(int para1,int para2);
  static void Main(string[] args)
  {
    /2、聲明委托變數d
    MyDelegate d;

    //3、實例化委托類型,傳遞的方法也可以為靜態方法,這裡傳遞的是實例方法
    d=new MyDelegate(new Program().Add);

    //4、委托類型作為參數傳遞給另一個方法
    MyMethod(d);
    Console.ReadKey();
  }

  //該方法的定義必須與委托定義相同,即返回類型為void,兩個int類型的參數
  void Add(int para1,int para2)
  {
    int sum=para1+para2;
    Console.WriteLine("兩個數的和為:"+sum);
  }

  //方法的參數是委托類型
  Private static void MyMethod(MyDelegate mydelegate)
  {
    //5、在方法中調用委托
    mydelegate(1,2);
  }
}

從上面的代碼可以得出委托使用的步驟:定義委托類型->聲明委托變數->實例化委托->作為參數傳遞給方法->調用委托。

 

3、為什麼要引入委托?

委托最大的作用,就是使得一個方法可以作為另一個方法的參數進行傳遞。

比如我們要實現一個打招呼的方法,但每個國家打招呼的方式是不一樣的,我們可能會使用switch的方式進行設計,但這樣做明顯導致可擴展性不足,每次增加一個新的打招呼方法都必須去修改case語句來適應新的需求。如果有了委托,情況就不一樣了:

class Program
{
  //定義委托類型
  public delegate void GreetingDelegate(string name);
  static void Main(string[] args)
  {
    //引入委托之後
    Program p=new Program();
    p.Greeting("李志",p.ChineseGreeting);
    p.Greeting("Tommy Li",p.EnglishGreeting);
    Console.ReadKey();
  }

  public void Greeting(string name,GreetingDelegate callback)
  {
    callback(name);
  }

  public void ChineseGreeting(string name)
  {
    Console.WriteLine("你好,"+name);
  }

  public void EnglishGreeting(string name)
  {
    Console.WriteLine("Hello,"+name);
  }
}

在引入委托之後,就可以把函數作為參數傳遞給另一個方法了。委托可以提高方法的可擴展性。

 

4、委托的本質

委托是一個類類型,從哪裡看得出來呢,就需要從IL代碼中找到答案。

C#代碼如下:

class Program
{
  public delegate void DelegateTest(int param);
  static void Main(string[] args)
  {
  }
}

 

從上圖中便可以得出委托DelegateTest是一個類,繼承自System.MulticastDelegate類型。並且該類包含了一個構造函數和3個方法。有了構造函數,我們才能使用new關鍵字來實例化委托類型。而Invoke方法則用來顯式地調用委托。此外,BeginInvoke和EndInvoke是兩個非同步方法(以後解釋什麼叫做非同步方法)。

在最開篇開始的代碼當中,我們使用mydelegate(1,2)來調用方法,這是隱式調用,其背後也是要通過調用Invoke方法來調用委托的。當時,我們使用顯式調用mydelegate.Invoke(1,2)也行。

 

5、委托鏈

C#中的委托同樣可以封裝多個方法。C#中把封裝多個方法的委托稱作委托鏈或多路廣播委托。

可以通過“+=”運算符,將多個委托對象鏈接到一個委托對象實例上,成為多路廣播委托實例。也可以使用“-=”運算符將某個委托從委托鏈對象上移除。

class Program
{
  //聲明一個委托類型
  public delegate void DelegateTest();
  static void Main(string[] args)
  {
    //用靜態方法來實例化委托
    DelegateTest dtstatic =new DelegateTest(Program.Method1);
    DelegateTest dtinstance=new DelegateTest(new Program().Method2);

    //定義一個委托對象,一開始初始化為null,即不代表任何方法
    DelegateTest delegatechain=null;

    //使用“+”符號鏈接委托,鏈接多個委托後就成為了委托鏈
    delegatechain+=dtstatic;
    delegatechain+=dtinstance;


    //delegatechain-=dtinstance;
    //調用委托鏈
    delegatechain();
    Console.Read();
  }

  private static vodid Method1()
  {
    Console.WriteLine("這是靜態方法");
  }

  private void Method2()
  {
    Console.WriteLine("這是實例方法");
  }
}

總結:委托,是C#中一個最基本最重要的特性。大家可以藉助反編譯工具好好看一下委托的IL代碼。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Reflec... ...
  • 位元組序,是指位元組在記憶體中的存儲順序。其又分為大端位元組(Big-Endian)序和小端位元組序(Little-Endian)。 以下摘自百度百科: a) Little-Endian就是低位位元組排放在記憶體的低地址端,高位位元組排放在記憶體的高地址端。 b) Big-Endian就是高位位元組排放在記憶體的低地址端 ...
  • 感謝廣大網友的熱心提醒,現已發現如下錯誤: 感謝 “ ”對畫布筆記系列的反饋(QQ:350223285) 這個是失誤,strokeStyle和stroke對應 待續。。。。 歡迎提出更多問題,感謝大家~ ...
  • using System; using System.Collections.Generic; public delegate void DExchange(ref T t1,ref T t2); public interface IExchange { void Swap(ref T t1,ref... ...
  • 異常處理彙總-資料庫系列 http://www.cnblogs.com/dunitian/p/4522990.html 後期會在博客首發更新:http://dnt.dkill.net/Article/Detail/313 錯誤如圖,怎麼執行都沒有自己想要的效果(return掉了,還有個啥???!!! ...
  • 為了方便Dapper操作可以使用Dapper的相關擴展dapper simplecrud。 1.首先點擊管理NuGet 2.在管理頁面中搜索 Dapper.SimpleCRUD並安裝 然後就可以使用該包下的擴展 經過好久的尋找找到該文章,隨便吐槽一下百度真的十分坑爹,找的無用信息太多 https:/ ...
  • .Net版本 2.0 SP2 4.0 操作系統 Windows 2000 SP4以上 Windows XP SP3以上 安裝包大小 NetFx20SP2_x86.exe 23.8 MBNetFx20SP2_ia64.exe 52.2 MBNetFx20SP2_x64.exe 46.3 MB 統一安裝 ...
  • 一、去App Store 裡面下載並安裝 Xcode 二、去Xamairn下載 Xamairn Studio、MonoFramework、Monotouch 並安裝 三、打開Xamairn Studio 在插件管理裡面下載 CocosSharp模版 四、新建項目 五、編寫代碼 六、運行調試 申明:未 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...