国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#中委托的基本概念介紹

2020-01-24 02:08:43
字體:
供稿:網(wǎng)友

最近在看深入理解C#,發(fā)現(xiàn)這是一本很不錯的書,將很多C#的知識點聯(lián)系了起來,更像是一本C#歷史書,從C# 1一步步介紹到C# 4。

所以準備一邊看,一邊整理讀書筆記。那么就先從委托開始。

委托是C#中一個非常重要的概念,從C# 1開始就有了委托這個核心概念,在C# 2和C# 3中委托又有了很多改進。

通過委托,我們可以將一個方法當作對象封裝起來,并且在運行時,我們可以通過這個對象來完成方法的調(diào)用。

委托的使用

首先,來個簡單的例子,蘋果只負責設(shè)計iphone,而把組裝iphone的工作委托給富士康做。

復制代碼 代碼如下:

class Apple
{
    //聲明委托類型
    public delegate void AssembleIphoneHandler();
    public AssembleIphoneHandler AssembleIphone;

    public void DesignIphone()
    {
        Console.WriteLine("Design Iphone By Apple");
    }
}

class Foxconn
{
    //與委托類型簽名相同的方法
    public void AssembleIphone()
    {
        Console.WriteLine("Assemble Iphone By Foxconn");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Apple apple = new Apple();
        Foxconn foxconn = new Foxconn();

        //創(chuàng)建委托實例
        apple.AssembleIphone = new Apple.AssembleIphoneHandler(foxconn.AssembleIphone);

        apple.DesignIphone();
        //委托實例的調(diào)用
        apple.AssembleIphone();
        //通過Invoke進行顯示調(diào)用
        //apple.AssembleIphone.Invoke();

        Console.Read();
    }
}

從上面的例子中,可以體會一下委托的使用。使用委托需要滿足4個條件:

1.聲明一個委托類型
2.找到一個跟委托類型具有相同簽名的方法(可以是實例方法,也可以是靜態(tài)方法)
3.通過相同簽名的方法來創(chuàng)建一個委托實例
4.通過委托實例的調(diào)用完成對方法的調(diào)用

委托類型和委托實例

當我們使用委托的時候,一定要注意這兩個概念。

委托類型,是通過delegate關(guān)鍵字聲明的一種類型,例如上面例子中的:

復制代碼 代碼如下:

public delegate void AssembleIphoneHandler();

注意,"AssembleIphoneHandler"是一個委托類型,它有自己的方法,可以創(chuàng)建相關(guān)的實例。通過"ILSpy"可以看到"AssembleIphoneHandler"的方法以及父類信息。

委托類型的聲明過程中描述了該委托類型的簽名(返回類型,參數(shù)列表),這個簽名就決定了那個方法可以用來創(chuàng)建一個改委托類型的委托實例;同時,這個簽名還表示了該委托實例調(diào)用的簽名。

而委托實例,就是通過委托類型進行實例化的對象,例如上面例子中的:

復制代碼 代碼如下:

apple.AssembleIphone = new Apple.AssembleIphoneHandler(foxconn.AssembleIphone);

在創(chuàng)建委托實例的過程中,我們需要找到一個跟委托類型簽名相同的方法來完成委托實例的創(chuàng)建。

委托的合并和刪除

在前面的例子中,委托實例(apple.AssembleIphone)只對應(yīng)一個操作(方法foxconn.AssembleIphone)。但是,每個委托實例都有一個操作列表,稱為委托實例的調(diào)用列表(invocation list)。在System.Delegate類中,有兩個靜態(tài)方法Combine和Remove,通過這兩個靜態(tài)方法,我們就可以進行兩個委托實例的調(diào)用列表的合并和刪除。

接著上面的例子進行修改,這次來看看委托的合并和刪除。

復制代碼 代碼如下:

class Foxconn
{
    //與委托類型簽名相同的方法
    public void AssembleIphone()
    {
        Console.WriteLine("Assemble Iphone By Foxconn");
    }

    public void PackIphone()
    {
        Console.WriteLine("Pack Ipnone By Foxconn");
    }

    public void ShipIphone()
    {
        Console.WriteLine("Ship Iphone By Foxconn");
    }
}


class Program
{
    static void Main(string[] args)
    {
        Apple apple = new Apple();
        Foxconn foxconn = new Foxconn();

        //創(chuàng)建委托實例
        apple.AssembleIphone = new Apple.AssembleIphoneHandler(foxconn.AssembleIphone);
        //apple.AssembleIphone += new Apple.AssembleIphoneHandler(foxconn.PackIphone);
        apple.AssembleIphone = (Apple.AssembleIphoneHandler)Delegate.Combine(apple.AssembleIphone, new Apple.AssembleIphoneHandler(foxconn.PackIphone));
        apple.AssembleIphone += new Apple.AssembleIphoneHandler(foxconn.ShipIphone);

        apple.DesignIphone();
        //委托實例的調(diào)用
        apple.AssembleIphone();
        //通過Invoke進行顯示調(diào)用
        //apple.AssembleIphone.Invoke();

        Console.Read();
    }
}

這次,我們在Foxconn類中加了打包和運輸?shù)姆椒ǎ@樣,可以通過Combine方法將組裝、打包和運輸三個操作合并到委托實例apple.AssembleIphone的調(diào)用列表中。

當我們調(diào)用委托實例的時候,委托實例的調(diào)用列表中的所有操作會依次被執(zhí)行。

注意,一般在代碼中,很少直接使用Combine和Remove方法的顯式調(diào)用,而是通過"+="和"-="操作符來實現(xiàn)。

委托是不易變的
這里有一點要提的是,委托是不易變的,一旦創(chuàng)建了一個委托實例后,這個實例的所有內(nèi)容都不能被改變了(就像string一樣,string也是不易變的)。

所以說Combine和Remove都沒有改變委托實例,都是新建了一個委托實例。

委托調(diào)用列表

在使用調(diào)用列表的時候,有些關(guān)鍵點需要注意一下,假如說一個委托實例的調(diào)用列表為[methodA, methodB, methodC]。那么當我們調(diào)用委托實例的時候,methodA, methodB, methodC會依次被執(zhí)行。

1.如果上面A-C三個方法都有返回值,我們只能得到最后一個操作的返回值,其他的返回值都將被忽略。
2.如果調(diào)用列表中的一個操作有異常,那么所有的下游操作都不會被執(zhí)行。

舉例,我們在PackIphone方法中加入一個異常,那么委托列表中的ShipIphone操作將不會被執(zhí)行到:

復制代碼 代碼如下:

class Foxconn
{
    //與委托類型簽名相同的方法
    public void AssembleIphone()
    {
        Console.WriteLine("Assemble Iphone By Foxconn");
    }

    public void PackIphone()
    {
        throw new NotImplementedException();
    }

    public void ShipIphone()
    {
        Console.WriteLine("Ship Iphone By Foxconn");
    }
}


class Program
{
    static void Main(string[] args)
    {
        Apple apple = new Apple();
        Foxconn foxconn = new Foxconn();

        //創(chuàng)建委托實例
        apple.AssembleIphone = new Apple.AssembleIphoneHandler(foxconn.AssembleIphone);
        //apple.AssembleIphone += new Apple.AssembleIphoneHandler(foxconn.PackIphone);
        apple.AssembleIphone = (Apple.AssembleIphoneHandler)Delegate.Combine(apple.AssembleIphone, new Apple.AssembleIphoneHandler(foxconn.PackIphone));
        apple.AssembleIphone += new Apple.AssembleIphoneHandler(foxconn.ShipIphone);

        apple.DesignIphone();
        //委托實例的調(diào)用
        try
        {
            apple.AssembleIphone();
        }
        catch
        {
            Console.WriteLine("an exception happened");
        }

        Console.Read();
    }
}

GetInvocationList

對于上面兩個問題,我們可以通過委托實例的GetInvocationList()方法,通過這個方法可以得到調(diào)用列表中的所有操作。

這樣,就可以顯示調(diào)用委托來進行異常處理或者返回值的保存。

復制代碼 代碼如下:

foreach (Apple.AssembleIphoneHandler method in apple.AssembleIphone.GetInvocationList())
{
    try
    {
        method();
    }
    catch
    {
        Console.WriteLine("an exception happened");
    }
}

總結(jié)

本文介紹了委托的基本概念,以及委托類型和委托實例的區(qū)別。

委托本質(zhì)上是一個派生自System.MulticastDelegate的類,我們可以通過特定的(與委托類型簽名相同)的方法創(chuàng)建委托實例,通過委托是,可以間接完成某些操作。

同時,可以通過Combine和Remove操作來進行委托實例的調(diào)用列表的合并和刪除。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 六枝特区| 榆社县| 商城县| 宿松县| 安阳市| 富平县| 防城港市| 永泰县| 施秉县| 柏乡县| 锡林郭勒盟| 河曲县| 辉县市| 襄城县| 华安县| 宁夏| 濉溪县| 连平县| 南投县| 佛学| 阜城县| 特克斯县| 屏东县| 桓台县| 库车县| 松潘县| 阿尔山市| 临夏县| 泰顺县| 德庆县| 沭阳县| 开封县| 罗定市| 肥城市| 渭南市| 乳源| 陈巴尔虎旗| 宣城市| 荣昌县| 承德市| 富锦市|