委托常常和事件在一起使用,可以理解委托是方法的容器,事件則是委托的另一種表現形式。委托和事件雖然寫得還比較多,不過也只是用的熟練而已,趁周末沒課好好鞏固下基礎,一點一點積累吧。
1.一個簡單的小例子
class Program { static void Main(string[] args) { People people = new People(); people.StartEat("吃"); Console.ReadLine(); } } class People { public void EatApple(string s) { Console.WriteLine(s+"蘋果"); } public void EatPear(string s) { Console.WriteLine(s+"梨子"); } public void StartEat(string str) { EatApple(str); } }
上面的代碼應該很好理解,但是在StartEat方法並不知道什麼時候該調用哪個方法進行輸出,因此在調用之前還需要定義一個枚舉EatWhat來進行判斷,也就是StartEat(string str,EatWhat eatWhat)。傳入的eatWhat枚舉判斷是吃蘋果還是梨子。但是這種寫法擴展性太差了,如果再加一個吃西瓜的方法,那麼還要更新枚舉,這樣反復的增加方法和枚舉顯然不是一個很好的做法。
顯然這裡要使用委托,為什麼要使用委托?最本質的原因是利用委托可使StartEat得到一個參數,而這個參數是方法,這樣我們想調用什麼就可以調用什麼了。
class Program { static void Main(string[] args) { People people = new People(); people.StartEat("吃", people.EatApple); people.StartEat("吃", people.EatPear); Console.ReadLine(); } } public delegate void EatDelegate(string name); class People { public void EatApple(string s) { Console.WriteLine(s+"蘋果"); } public void EatPear(string s) { Console.WriteLine(s + "梨子"); } public void StartEat(string str,EatDelegate eatDelegate) { eatDelegate(str); }
}
2.多播委托
委托的特殊之處在於,我們以前定義的所有對象都包含數據,而委托包含的只是方法的地址。在上面例子的基礎上,我們還可以實現多播委托。多播委托就是講多個方法賦給同一個委托,當調用這個委托的時候,將依次調用其綁定的方法。下面是對Program類的改動。
class Program { static void Main(string[] args) { People people = new People(); EatDelegate del = people.EatPear; del += people.EatApple; people.StartEat("吃", del); //既然可以對委托添加方法,那麼也可以對委托取消方法的綁定 del -= people.EatPear; Console.ReadLine(); } }
3.委托和事件
在上面的例子中,我們給StartEat方法傳參時需要傳入2個參數,而且還需要在Main方法中得到委托對象。因此我們可以將委托封裝到People類裡面,使傳參時只傳入一個參數,這就是用到了封裝的思想。
class Program { static void Main(string[] args) { People people = new People(); people.del = people.EatPear; people.del += people.EatApple; people.StartEat("吃"); Console.ReadLine(); } } class People { public EatDelegate del; public void EatApple(string s) { Console.WriteLine(s+"蘋果"); } public void EatPear(string s) { Console.WriteLine(s + "梨子"); } public void StartEat(string str) { if (del != null) { del(str); } } }
現在我們的委托對象和一般的變量沒有什麼區別,外部類訪問到People對象就可以拿到這個委托變量。假如現在在類裡面聲明一個字段,一般我們會封裝字段采用屬性。同樣的,對於委托我們也要封裝,這樣在類的內部,委托變量總是私有,但是在外部,依舊可以使用+=和-=的訪問操作。接下來我們對代碼進行改寫。
static void Main(string[] args) { People people = new People(); //現在已經不能使用=來給事件對象賦值,而只能使用+=和-=來進行操作 people.eventDelegate += people.EatApple; people.eventDelegate+=people.EatPear; people.StartEat("吃"); Console.ReadLine(); } } class People { //簡單點理解,事件其實就可以理解為一個封裝了委托的變量 //如果去看代碼執行的源碼,會發現eventDelegate變量,其實就是一個委托對象,只不過它是私有的,修飾符為private //這個委托變量有2個方法 ,且只有2個方法,+=對應addon,-=對應於removeon方法。 public event EatDelegate eventDelegate; public void EatApple(string s) { Console.WriteLine(s+"蘋果"); } public void EatPear(string s) { Console.WriteLine(s + "梨子"); } public void StartEat(string str) { eventDelegate(str); } }