1. 程式人生 > >c#事件機制

c#事件機制

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;

        }

    }