天天看點

委托與事件(淺度分析)—委托

前言

對于委托和事件,初次接觸是在《大話設計模式》這本書中,但是裡面隻是說明了一下委托和事件是如何使用的,并沒有詳細的講解委托和事件是什麼,是以不甚了解。因為不清楚委托和事件,是以每次想到它心裡就很不舒服,總有一個解不開的結。現在對于它們稍微了解了一點兒,心裡的石頭也可以暫時放一放了。

委托由來

先說一下我自己對于委托的了解:委托的作用就是可以把方法當做參數一樣使用。進而可以避免大量使用判斷語句,也使程式具有更好的擴充性。可能看完上面的話,不知道什麼意思,接下來就一步步分析。

1.先來看一個例子:

//打招呼
public void GreetPeople(string name)
{
    ChineseGreeting(name);
}
//中國人打招呼
public void ChineseGreeting(string name)
{
    Console.WriteLine("你好," + name);
}
           

上面的語句很容易了解吧,用漢語打招呼可能有的外國人聽不懂,那怎麼辦呢?再增加一個英國人打招呼的方法呗。

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

那麼,相應的 GreetPeople 方法也要更改,否則怎麼知道應該用哪種方法向别人打招呼呢?當然為了輸入的正确性,可以再用一個枚舉将這兩種語言封裝起來。

public enum Language
{
    English,
    Chinese
}
public void GreetPeople(string name, Language lang)
{
    swith(lang)
    {
        case Language.English:
            EnglishGreeting(name);
            break;
        case Language.Chinese:
            ChineseGreeting(name);
            break;
    }
}
           

雖然上面的問題解決了,可是如果需要再增加日本人,南韓人的打招呼的方法呢?還得再修改 GreetPeople 的方法,這樣就違背了“開閉原則”,不利于程式的擴充。

  2.接下來,問題又來了:既然不想違背“開閉原則”,有沒有一種解決辦法呢?可不可以直接把方法當做參數傳進 GreetPeople 方法裡,然後直接調用傳進去的方法,這樣就避免了選擇,添加其他打招呼的方法時也不需要更改 GreetPeople 方法了。用僞代碼舉一個示例:

public GreetPeople(一種類型  方法)
{
    //直接調用方法就可以了,無需判斷
    方法(name);
}
           

  答案就是:當然有!接下來就是委托登場了。沒錯,上面的一種類型指的就是委托類型。是以說委托隻是一種類型,隻不過略微特殊一點,它是把方法當做參數。

委托的作用

大家都知道,方法不可能全寫在一個類中,一般方法都會分布在不同的類中,那如果想跨類調用方法,應該怎麼辦呢?有的人說利用多态就可以啊。很正确,利用多态是可以實作,但是前提是還得繼承父類或實作接口。而委托無需這樣,就可以跨類調用。接下來,對比一下:

//利用多态實作
public interface IGreeting
{
    void GreetingPeople(string name);
}
public class EnglishGreeting : IGreeting
{
    public void GreetingPeople(string name)
    {
        Console.WriteLine("Hello," + name);
    }
}
public class ChieseGreeting : IGreeting
{
    public void GreetingPeople(string name)
    {
        Console.WriteLine("你好," + name);
    }
}
class Program
{
    private static void GreetPeople(string name,IGreeting makeGreeting)
    {
        makeGreeting.GreetingPeople(name);
    }
    static void Main(string[] args)
    {
        GreetPeople("Vijay",new EnglishGreeting());
        GreetPeople("張偉傑",new ChieseGreeting());
        Console.Read();
    }
}
           
//利用委托實作
public delegete void GreetingDelegate(stirng name);
class Program
{
    private static void GreetPeople(string name,GreetingDelegate makeGreeting)
    {
        makeGreeting(name);
    }
    static void Main(string[] args)
    {
        GreetPeople("Vijay",EnglishGreeting);
        GreetPeople("張偉傑",ChieseGreeting);
        Console.Read();
    }
}
           

通過比較可以發現,利用多态,還需要定義接口或者繼承父類,而且在調用的時候還需要執行個體化。而利用委托,直接将方法名傳遞就可以。

委托的綁定

那麼委托的綁定過程又是怎麼樣呢?先不管它,先來想一個問題:既然委托是一種類型,可不可以像普通類型那樣進行指派呢?比如:string name = “vijay”;

static void Main(string[] args)
{
    GreetingDelegate delegate1;
    delegate1 = EnglishGreeting;     //向委托變量指派
    delegate1 += ChineseGreeting;    //等于是将第二個方法存到一個連結清單中
    //将依次調用 EnglishGreeting 和 ChineseGreeting 方法
    delegate1("Vijay");
    Console.Read();
}
           

這樣也是可以的,但是注意第一次用到是指派“=”,第二次用的是“+=”。如果第一次也用“+=”就會出現“使用了未指派的局部變量”的編譯錯誤。

其實 delegate1 = EnglishGreeting;是下面這樣的:

我認為給委托綁定方法其實就是将方法賦給一個委托類型的變量。隻不過不同于其他的普通類型,委托可以有多個指派,即可以綁定多個方法。

小結

委托是什麼?委托隻不過是一種類型,也沒有多麼的高大上,可以将方法賦給它的一種類型,暫時可以這麼通俗的了解。一般來說,有委托就有事件,委托和事件是配合使用的,下一篇部落格就說明一下事件是什麼。