委托常常和事件在一起使用,可以理解委托是方法的容器,事件則是委托的另一種表現形式。委托和事件雖然寫得還比較多,不過也只是用的熟練而已,趁周末沒課好好鞏固下基礎,一點一點積累吧。
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);
}
}

