c#事件機制
阿新 • • 發佈:2018-12-13
c#有一個很重要的高階語言特性,叫做事件,有很多人說事件就是委託,其實不然,事件包含委託,但絕對不是委託,因為事件只能在類中宣告,而委託可以在函式也就是方法中宣告,另外,事件的方法也少於委託,那麼什麼是事件呢,使用事件,需要在類中宣告,並且事件始終是共有方法,而且使用事件需要在型別前加上event,而且事件型別一定是一個委託型別。
那麼什麼是委託呢,委託其實類似於c語言和c++語言的函式指標,因為c#中取消了指標,所以就不存在函式指標的概念了,因為函式指標也是一種指標,但是函式指標很有用處,比如你給一個函式傳遞一個函式指標,而此函式的資料是不變的,這樣就可以動態改變函式中的資料,因為傳入的函式指標變化,c#加入了委託概念,委託是型別安全,事實上,委託是一個類,委託類似函式指標,不瞭解委託概念的人可以瞭解函式指標。
delegate void mydelegate(int x);//首先在使用事件之前,必須定義一個委託,以後事件的註冊函式必 //須於此委託函式簽名一致 class publisher//釋出者 { public event mydelegate myevent;//事件出現在類中,必須共有,加上事件公共字,並使用委 //託型別 public void Startup() { for(int i=0;i<100;++i) { if(i%12==0&&myevent!=null) { myevent(i);//呼叫事件方法 } } } } class subcribe//訂閱者 { public subcribe(publisher pb) { pb.myevent += regisiterfunc; }//釋出者與訂閱者結合 public int Id { get;private set; } public void regisiterfunc(int x)//訂閱者提供事件所需的註冊函式 { Id++; Console.WriteLine(Id); Console.WriteLine("code id={0}", x); Console.WriteLine("___________"); } }
大家可以看到,使用事件必須要五個步驟,這五個步驟不能少,首先,1,定義委託型別,2,在一個類也就是釋出者定義事件,3,在釋出者中呼叫事件,當然是在合適的時機,然後還有兩個步驟,即在訂閱者,4,也就是另外一個至少一個或很多的類中提供事件所需,且與事件簽名一模一樣的註冊函式,另外,5,需要在訂閱者中匯入釋出者類的事件介面,使得兩者咬合。
現在在看一個具體的例子,完全是我自己原創:
delegate int mydelegate1(object o);//定義委託 class myDefineArgs : EventArgs//這個類可以用於事件引數,也可不用 { public myDefineArgs(string name,double price) { Name = name;Price = price; } public string Name { get; set; } public double Price { get; set; } } class shop { public event mydelegate1 myevent;//定義事件 public void updateprice(customer c,customer1 c1)//事件啟發函式 { while (true) { int i = -1; i = Convert.ToInt32(Console.ReadLine());//與下面的效果一樣 // i = System.Int32.Parse(Console.ReadLine()); if (i == 0) { myevent -= c.testfunc; myevent(this); myevent += c.testfunc; } else if (i == 1) { myevent -= c1.myregisterfunc; myevent(this); myevent += c1.myregisterfunc; } } } } //然後下面在寫兩個類,這兩個類有相同部分,比如全部是消費者類,與超市類對應,但是這兩個消費者類各有不同,因此寫成兩個,因為提供註冊的事件函式不同,這樣可以減少程式碼複雜度,即兩個釋出者提供註冊函式,分別與shop中的事件連結,然後再shop中集中處理 class customer { public customer(shop s) { s.myevent+=testfunc; } public List<myDefineArgs> buygoods = new List<myDefineArgs>(); public int testfunc(object o) { foreach (var arg in buygoods) { Console.WriteLine(o.ToString()); if (arg.Price > 1000) { Console.WriteLine("expensive goods {0} {1}", arg.Name, arg.Price); } else if (arg.Price <= 1000) { Console.WriteLine("cheap goodes {0} {1}", arg.Name, arg.Price); } } return 0; } } class customer1 { public List<myDefineArgs> buygoods = new List<myDefineArgs>(); public customer1(shop s) { s.myevent += myregisterfunc; } public int myregisterfunc(object o) { foreach (var arg in buygoods) { switch (arg.Name) { case "football": Console.WriteLine("footaball {0}", arg.Price); break; case "basketball": Console.WriteLine("bascket {0}", arg.Price); break; default: break; } } return 0; } }