欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解C#中的委托

 更新時間:2017年01月17日 09:16:37   作者:鄒瓊俊  
本文主要介紹了C#中委托的相關知識。具有一定的參考價值,下面跟著小編一起來看下吧

委托這個東西不是很好理解,可是工作中又經(jīng)常用到,你隨處可以看到它的身影,真讓人有一種又愛又恨的感覺,我相信許多人被它所困擾過。

一提到委托,如果你學過C語言,你一定會馬上聯(lián)想到函數(shù)指針。

什么是委托?委托是C#中類型安全的,可以訂閱一個或多個具有相同簽名方法的函數(shù)指針。委托可以把函數(shù)做為參數(shù)傳遞,其實際意義便是讓別人代理你的事情。委托可以看做是函數(shù)的指針,整數(shù)可以用整數(shù)變量指向它,對象可以用對象變量指向它,

函數(shù)也可以用委托變量指向它。我們可以選擇將委托類型看做只定義了一個方法的接口,而委托的實例可以看做是實現(xiàn)了那個接口的一個對象。

使用委托,必須滿足4個條件:

  • 聲明委托類型;
  • 必須有一個方法包含了要執(zhí)行的代碼;
  • 必須創(chuàng)建一個委托實例;
  • 必須調(diào)用(invoke)委托實例。

委托的申明

聲明委托的方式:delegate 返回值類型 委托類型名(參數(shù))

委托的申明和接口方法的申明基本上一致,只是在返回類型關鍵字的前面多了一個delegate關鍵字。還有就是委托一般聲明為public類型,因為它隨時要供別人調(diào)用的。

委托的本質(zhì)也是一個類型。我們聲明一個類可以進行實例化,同樣委托也可以進行實例化。

有如下四種委托:

//1.無參數(shù)無返回值
    public delegate void NoParaNoReturnEventHandler();
    //2.有參數(shù)無返回值
    public delegate void WithParaNoReturnEventHandler(string name);
    //3.無參數(shù)有返回值
    public delegate string NoParaWithReturnEventHandler();
    //4.有參數(shù)有返回值
    public delegate string WithParaWithReturnEventHandler(string name);

如果代碼想要執(zhí)行操作,但不知道操作細節(jié),一般可以使用委托。例如, Thread類之所以知道要在一個新線程里運行什么,唯一的原因就是在啟動新線程時,向它提供了一個ThreadStart或ParameterizedThreadStart委托實例。

Thread th = new Thread(Test);
th.Start();
public Thread(ThreadStart start);
public delegate void ThreadStart();

ThreadStart是一個無參無返回值的委托。

    static void Test()
    {
      Console.WriteLine("線程方法");
    }

這個Test方法的函數(shù)簽名必須和委托ThreadStart的函數(shù)簽名一致。

委托的調(diào)用

必須先實例化委托,然后再調(diào)用。

函數(shù)的簽名和委托的簽名必須一致。NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo;,編譯器幫我們進行了new,但是不能寫成NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo();

因為這樣就成為了函數(shù)調(diào)用。

#region 無返回值委托調(diào)用
    public static void Show()
    {
      //實例化委托
      NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = new NoParaNoReturnEventHandler(ConsoleInfo);
      //NoParaNoReturnEventHandler _NoParaNoReturnEventHandler = ConsoleInfo; //簡寫
      //委托調(diào)用 通過Invoke()調(diào)用,或者可以直接省略
      _NoParaNoReturnEventHandler.Invoke();
      //_NoParaNoReturnEventHandler();
    }
    private static void ConsoleInfo()
    {
      Console.WriteLine("無參數(shù)無返回值的函數(shù)調(diào)用");
    } 
    #endregion

沒有委托就沒有異步,異步正是因為委托的存在。

_NoParaNoReturnEventHandler.BeginInvoke(null,null); //異步調(diào)用

為什么要使用委托

我們完全可以直接調(diào)用方法,為什么還需要通過一個委托來調(diào)用呢?委托有什么意義?

解耦,對修改關閉,對擴展開放。邏輯分離。

你可以把委托理解為函數(shù)的父類,或者是一個方法的占位符。

我們來看下代碼,假設有2個方法,一個說英語,一個說漢語,而這2個方法的函數(shù)簽名是一樣的。

public static void SayChinese(string name)
    {
      Console.WriteLine("你好," + name);
    }
    public static void SayEnglish(string name)
    {
      Console.WriteLine("hello," + name);
    }

那么我們在外部調(diào)用的時候,

  MyDelegate.SayChinese("張三");
  MyDelegate.SayEnglish("zhangsan");

如果要調(diào)用這兩個不同的方法,是不是要寫不同的調(diào)用代碼

我們能不能只一個方法調(diào)用呢?修改代碼如下:

public static void Say(string name,WithParaNoReturnEventHandler handler)
    {
      handler(name);
    }
   public static void SayChinese(string name)
    {
      Console.WriteLine("你好," + name);
    }
    public static void SayEnglish(string name)
    {
      Console.WriteLine("hello," + name);
    }

這樣,只通過一個方法Say來進行調(diào)用。

如何調(diào)用呢?如下三種調(diào)用方式:

      WithParaNoReturnEventHandler _WithParaNoReturnEventHandler = new WithParaNoReturnEventHandler(MyDelegate.SayChinese);
      MyDelegate.Say("張三",_WithParaNoReturnEventHandler);
      MyDelegate.Say("張三", delegate(string name) { Console.WriteLine("你好," + name); }); //匿名方法
      MyDelegate.Say("張三", (name) => { Console.WriteLine("你好," + name); }); //lambda表達式

以上代碼使用了幾種調(diào)用方式,這些調(diào)用方式都是隨著C#的升級而不斷優(yōu)化的。第一種是C#1.0中就存在的傳統(tǒng)調(diào)用方式,第二種是C#2.0中的匿名方法調(diào)用方式,所謂匿名方法,就是沒有名字的方法,當方法只調(diào)用一次時使用匿名方法最合適不過了。C#3中的lambda表達式。其實泛型委托同樣是被支持的,而.NET 3.5則更進一步,引入了一組名為Func的泛型委托類型,它能獲取多個指定類型的參數(shù),并返回另一個指定類型的值。

lambda表達式

lambda表達式的本質(zhì)就是一個方法,一個匿名方法。

如果方法體只有一行,無返回值,還可以去掉大括號和分號。

MyDelegate.Say("張三", (name) => Console.WriteLine("你好," + name));

如果方法體只有一行,有返回值,可以去掉大括號和return。

WithParaWithReturnEventHandler _WithParaWithReturnEventHandler = (name)=>name+",你好";

從.NET3.5開始,基本上不需要我們自己來申明委托了,因為系統(tǒng)有許多內(nèi)置的委托。

Action和Func委托,分別有16個和17個重載。int表示輸入?yún)?shù),out代表返回值,out參數(shù)放置在最后。

Action表示無返回值的委托,F(xiàn)unc表示有返回值的委托。因為方法從大的角度來分類,也分為有返回值的方法和無返回值的方法。

也就是說具體調(diào)用什么樣的方法,完全由調(diào)用方?jīng)Q定了,就有了更大的靈活性和擴展性。為什么這么說,如果我有些時候要先說英語再說漢語,有些事時候要先說漢語再說英語,如果沒有委托,我們會怎么樣實現(xiàn)?請看如下代碼:

public static void SayEnglishAndChinese(string name)
    {
      SayEnglish(name);
      SayChinese(name);
    }
    public static void SayChineseAndEnglish(string name)
    {
      SayChinese(name);
      SayEnglish(name);
    }

如果又突然要添加一種俄語呢?被調(diào)用方的代碼又要修改,如此循環(huán)下去,是不是要抓狂了?隨著不斷添加新語種,代碼會變得越來越復雜,越來越難以維護。這樣的代碼耦合性非常高,是不合理的,也就是出現(xiàn)了所謂的代碼的壞味道,你可以通過設計模式(如觀察者模式等),在不使用委托的情況下來重構(gòu)代碼,但是實現(xiàn)起來是非常麻煩的,要寫很多更多的代碼...

委托可以傳遞方法,而這些方法可以代表一系列的操作,這些操作都由調(diào)用方來決定,就很好擴展了,而且十分靈活。我們不會對已有的方法進行修改,而是只以添加方法的形式去進行擴展。

可能有人又會說,我直接在調(diào)用方那里來一個一個調(diào)用我要執(zhí)行哪些方法一樣可以實現(xiàn)這樣的效果???

可你有沒有想過,你要調(diào)用的是一系列方法,你根本無法復用這一系列的方法。使用委托就不一樣了,它好比一個方法集合的容器,你可以往里面增減方法,可以復用的。而且使用委托,你可以延時方法列表的調(diào)用,還可以隨時對方法列表進行增減。委托對方法進行了再一次的封裝。

總結(jié):也就是當你只能確定方法的函數(shù)簽名,無法確定方法的具體執(zhí)行時,為了能夠更好的擴展,以類似于注入方法的形式來實現(xiàn)新增的功能,就能體現(xiàn)出委托的價值。

委托和直接調(diào)用函數(shù)的區(qū)別:用委托就可以指向任意的函數(shù),哪怕是之前沒定義的都可以,而不用受限于哪幾種。

多播委托

組合的委托必須是同一個類型,其相當于創(chuàng)建了一個按照組合的順序依次調(diào)用的新委托對象。委托的組合一般是給事件用的,用普通委托的時候很少用。

通過+來實現(xiàn)將方法添加到委托實例中,-來從委托實例中進行方法的移除。

+和-純粹是為了簡化代碼而生的,實際上其調(diào)用的分別是Delegate.Combine方法和Delegate.Remove。

如果委托中存在多個帶返回值的方法,那么調(diào)用委托的返回值是最后一個方法的返回值。

public static void MultipleShow()
    {
      //多播委托
      NoParaWithReturnEventHandler _NoParaWithReturnEventHandler = new NoParaWithReturnEventHandler(GetDateTime);
      _NoParaWithReturnEventHandler += GetDateTime;
      Console.WriteLine(_NoParaWithReturnEventHandler());
    }
    public static string GetDateTime()
    {
      return string.Format("今天是{0}號。", DateTime.Now.Day.ToString());
    }

委托總結(jié):

  • 委托封裝了包含特殊返回類型和一組參數(shù)的行為,類似包含單一方法的接口;
  • 委托類型聲明中所描述的類型簽名決定了哪個方法可用于創(chuàng)建委托實例,同時決定了調(diào)用的簽名;
  • 為了創(chuàng)建委托實例,需要一個方法以及(對于實例方法來說)調(diào)用方法的目標;
  • 委托實例是不易變的,就像String一樣;
  • 每個委托實例都包含一個調(diào)用列表——一個操作列表;
  • 事件不是委托實例——只是成對的add/remove方法(類似于屬性的取值方法/賦值方法)。

常見使用場景:窗體傳值、線程啟動時綁定方法、lambda表達式、異步等等。

生活中的例子:現(xiàn)在不是大家都在搶火車票嗎,使用云搶票就相當于使用委托,你可以直接自己買票,也可以托管于云搶票,自己搶票的話,在快要開槍的時候,你必須時刻刷新,下單輸驗證碼等等,使用云搶票的話,你只要放票前,提前輸入搶票信息,就再也不需要你管了,自動出票,你根本不需要知道云搶票那邊是怎么幫你實現(xiàn)搶票的。相同時間和車次可以做成一個委托實例,有很多人都通過這個委托實例來進行搶票操作。

源碼下載:http://pan.baidu.com/s/1dEPlxJj

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關文章

  • C#實現(xiàn)帶搜索功能的ComboBox

    C#實現(xiàn)帶搜索功能的ComboBox

    這篇文章主要為大家詳細介紹了C#如何實現(xiàn)帶搜索功能的ComboBox,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • C# 鼠標穿透窗體功能的實現(xiàn)方法

    C# 鼠標穿透窗體功能的實現(xiàn)方法

    通過以下代碼,在窗體啟動后調(diào)用方法SetPenetrate() 即可實現(xiàn)窗體的穿透功能,有需要的朋友可以參考一下
    2013-10-10
  • c# Winform同一數(shù)據(jù)源多個控件保持同步

    c# Winform同一數(shù)據(jù)源多個控件保持同步

    通過對控件屬性設置數(shù)據(jù)源綁定,利用Windows數(shù)據(jù)更改通知這一特性,只要訂閱(設定綁定)的控件都能接收到數(shù)據(jù)的變化通知。 通過DataBindings方法實現(xiàn)雙向數(shù)據(jù)綁定
    2021-06-06
  • C#實現(xiàn)rabbitmq 延遲隊列功能實例代碼

    C#實現(xiàn)rabbitmq 延遲隊列功能實例代碼

    本篇文章主要介紹了C#實現(xiàn)rabbitmq 延遲隊列功能實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • C# 透明窗體制作實現(xiàn)方法比較分析

    C# 透明窗體制作實現(xiàn)方法比較分析

    制作透明窗體辦法有好幾種,各有優(yōu)缺點.我們先來看看C#本身提供的辦法:通過設置窗體的 TransparencyKey實現(xiàn),需要的朋友可以了解下
    2012-12-12
  • C#實現(xiàn)學生成績管理系統(tǒng)

    C#實現(xiàn)學生成績管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C#實現(xiàn)學生成績管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C#讀取二進制文件方法分析

    C#讀取二進制文件方法分析

    這篇文章主要介紹了C#讀取二進制文件方法,較為詳細的分析了C#讀取二進制文件的原理與注意事項,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-01-01
  • C# DataTable常見用法匯總

    C# DataTable常見用法匯總

    這篇文章主要介紹了C# DataTable常見用法,幫助大家更好的理解和學習c#,感興趣的朋友可以了解下
    2020-08-08
  • C#中參數(shù)數(shù)組、引用參數(shù)和輸出參數(shù)示例詳解

    C#中參數(shù)數(shù)組、引用參數(shù)和輸出參數(shù)示例詳解

    這篇文章主要給大家介紹了關于C#中參數(shù)數(shù)組、引用參數(shù)和輸出參數(shù)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-05-05
  • C#實現(xiàn)獲取IIS站點及虛擬目錄信息的方法

    C#實現(xiàn)獲取IIS站點及虛擬目錄信息的方法

    這篇文章主要介紹了C#實現(xiàn)獲取IIS站點及虛擬目錄信息的方法,可實現(xiàn)獲取IIS站點信息及物理路徑等功能,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10

最新評論