詳細從淺到深講解委託和事件


 委託和事件在.net中的應用非常廣泛,但是很多人都不太瞭解爲什麼使用委託?委託的應用有什麼優點?接下來就爲大家從什麼是委託,委託的實現,爲什麼要使用委託,三個部分進行由淺到深的講解,存在問題的地方,還請大家指正

 

1.什麼是委託?

 從語言的角度來講,委託就是把事情託付給別人或別的機構辦理.

 請看下面一段代碼:

public class example:Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        showInfo del = FunShowInfo;//委託和隨string等類型一樣,可以定義一種參數類型
        Response.Write(del(6).ToString());
    }
    public delegate int showInfo(int i);

    public int FunShowInfo(int info)
    {
        return info;
    }
}

運行結果: 在頁面上顯示 6


這個例子中,我們把FunShowInfo委託給del,當執行del的時候實現FunShowInfo的運行結果;

說道這裏,大家應該對委託有了一定的認識,那麼在C#中委託是什麼類型呢?

委託是一個類,它定義了方法的類型,使得可以將方法當作另一個方法的參數來進行傳遞.

委託可以定義在類的內部或外部,因爲委託本身就是類,所以類可以定義在哪委託就可以定義在哪。

委託和string等類型一樣,可以定義一種參數類型,然後把方法賦值給委託;不同於string的是,他可以接受多個方法的委託,然後調用委託的時候可以調用多個方法;在後面的講解中會講道;

 

2.委託的實現

通俗的可以用下面地話描述:

         1.定義一個委託,用關鍵字delegate ,具有與事件相同的返回值和參數;

         2.聲明一個委託,並把事件傳給它;

         3.把委託作爲參數傳遞,調用;

 

3.爲什麼使用委託

看完上面的例子,大家可能會疑問,我直接可以寫成下面的代碼:

public class example : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
       Response.Write(FunShowInfo(4));
    }
    public int FunShowInfo(int info)
    {
        return info;
    }
}

會實現一樣的效果,用委託實現還多寫了幾行代碼;它的意義何在呢?

好,那麼請看下面的例子:

public class example : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Hello(langurage.English, "Demi");
        }

        public enum langurage
        {
            Chinese, English
        }

        public void EnglishGreeting(string name)
        {
            Response.Write("Morning" + "\r\n" + name);
        }
        public void ChineseGreeting(string name)
        {
            Response.Write("你好" + "\r\n" + name);
        }
        public void Hello(langurage lan, string name)
        {
            switch (lan)
            {
                case langurage.English:
                    EnglishGreeting(name);
                    break;
                case langurage.Chinese:
                    ChineseGreeting(name);
                    break;
            }
        }
    }

這個代碼實現的是.當頁面加載的時候,會根據傳入的枚舉類型和string類型的參數,執行不同的問候方法;但是這個方案的可擴展性很差,如果日後我們需要再添加韓文、日文問候方法,就不得不反覆修改枚舉和Hello() Case方法,以適應新的需求。

思考:

我們來看Hello這個方法:

Hello(langurage lan, string name)

它接受一個string類型的name參數.然後根據傳入的langurage 類型參數lan來switch case判斷執行的方法體;試想一下,如果我們傳入的參數不通過switch case判斷,只是根據參數本身就可以知道執行的方法體,那麼豈不是省去了switch case語句,模型如下:

Hello(string name,***LangurageGreeting)

{

LangurageGreeting(name);

}

那怎麼實現呢?這裏就需要用到委託了----------------請看代碼--------------:

 

    public class example : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Hello("Demi", EnglishGreeting);
            Hello("楊冪", ChineseGreeting);
        }

        public delegate void LangurageGreeting(string name);

        private void EnglishGreeting(string name)
        {
            Response.Write("Morning, " + name + "<br/><br/>");
        }

        private void ChineseGreeting(string name)
        {
            Response.Write("早上好, " + name);
        }

        //注意此方法,它接受一個GreetingDelegate類型的方法作爲參數
        private static void Hello(string name, LangurageGreeting MakeGreeting)
        {
            MakeGreeting(name);
        }
    }

總結: 委託是一個類,它定義了方法的類型,使得可以將方法當作另一個方法的參數來進行傳遞.以避免在程序中大量使用If-Else(Switch)語句,同時使得程序具有更好的可擴展性。

委託是一個引用類型,它具有引用類型所具有的通性.引用類型保存的不是實際值,而是保存對存儲在託管堆中的對象的引用.委託保存的是對函數(方法)的引用.

 

在剛開始的時候我們說過,委託和 類型 string 的地位一樣,都是定義了一種參數類型,那麼,我是不是也可以這麼使用委託?

 public class example : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            LangurageGreeting english = EnglishGreeting;
            LangurageGreeting chinese = ChineseGreeting;

            //這裏我們可以給此委託變量再綁定一個方法
            //english += ChineseGreeting;  
            //給此委託變量取消取消一個方法
            //english -= ChineseGreeting; 
            //需要注意一點是,第一次用的“=”,是賦值的語法;第二次,用的是“+=”,是綁定的語法。如果第一次就//使用“+=”,將出現“使用了未賦值的局部變量”的編譯錯誤。
          
            Hello("Demi", english); 
            Hello("楊冪", chinese);
        }

        public delegate void LangurageGreeting(string name);

        private void EnglishGreeting(string name)
        {
            Response.Write("Morning, " + name + "<br/><br/>");
        }
        private void ChineseGreeting(string name)
        {
            Response.Write("早上好, " + name);
        }
        //注意此方法,它接受一個GreetingDelegate類型的方法作爲參數
        private static void Hello(string name, LangurageGreeting MakeGreeting)
        { 
            MakeGreeting(name); 
        }
    }


 好了,希望能對你有所幫助.

 

 

 

發佈了88 篇原創文章 · 獲贊 16 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章