2013年4月30日 星期二

委派Delegate教學

本文參考
http://rfid-fantasy.blogspot.tw/2009/07/c-delegate.html
http://big5.webasp.net/article/6/5592_print.htm
http://blog.xuite.net/johnnyle/worker/16891057
http://www.dotblogs.com.tw/yc421206/archive/2009/02/16/7206.aspx
關於Delegate 理論上用於,代理類別的一種技巧
用於物件導向,類別與方法
簡單來說 就是代理呼叫的意思,而類別中也可以使用委派
而委派也已再次委派 下面直接看範例

在範例之前 紀錄一下 運行原理!

假如要用Delegate寫一個簡易計算機程式
原理則是
先建立 +-*/ 4大類別
在宣告委派Delegate
編輯完後
在觸發控制項中
建立Delegate 指定為null值,稍後在實體化,並指派方法
建立2個數值型態放數字
與1個字串型態放+-*/字元
再利用switch 判斷 輸入的字串為和??
再利用case 做字元判斷
判斷成功 將委派物件實體化並且 指定類別
委派設定完後~
將套入數值參數   \\數值型態=委派(數值參數)
當委派套入數值參數時,委派將呼叫剛才指定的類別
並且將參數傳給類別,類別運算完之後 return給委派
委派再給 新宣告的 數值型態
數值型態在SHOW出給使用者運算結果!
來看CODING!

首先 先建立 委派 跟 類別

delegate int GGYY(int GG, int YY);//先宣告等等要呼叫的委派叫GGYY
//在這邊要注意 委派的參數 型態必須與呼叫的方法 是一樣的
        //下面宣告4個方法 注意 傳入參數的型態必須一樣
        private int addd(int a, int b)//宣告方法
        {
            //加
            return a + b;//回傳a+b
        }
        private int subtract(int a, int b)
        {
            //減
            return a - b;
        }
        private int multiply(int a, int b)
        {
            //乘
            return a * b;
        }
        private int divide(int a, int b)
        {
            //除
            return a / b;
        }
再來我們在 控制項中 來運用委派 控制項是BUTTON

private void button5_Click(object sender, EventArgs e)
        {
            GGYY ARI=null;//如果不指定個NULL直 編識器會發生錯誤
            //錯誤是Use of unassigned local variable 'ARI' 沒有初始化ari
            //所以要給一個null直 但不能是 數值 因為是delegate委派方法
            string FUN = textBox2.Text;//輸入加減乘除+-*/
            int x = int.Parse(textBox1.Text);//輸入 計算數值1
            int y = int.Parse(textBox3.Text);//輸入計算數值2
            switch (FUN)//判斷FUN是輸入什麼?
            {//索取輸入FUN的運算子    然後先建立所指定的物件
                case "+":
                    ARI = new GGYY(addd);//如果是用add必須+THIS 複寫ADD
                    break;
                case "-":
                    ARI = new GGYY(subtract);
                    break;
                case "*":
                    ARI = new GGYY(multiply);
                    break;
                case "/":
                    ARI = new GGYY(divide);//實作委派
                    break;
            }
            //建立好之後 ARI帶入X,Y直 呼叫委派
            //呼叫的哪一個委派物件決定剛剛SWITCH所選擇的物件
            int anser = ARI(x, y);//呼叫委派 等待委派方法運算完傳回給ANSER
            label5.Text = anser.ToString();//在SHOW給LABEL
        }

上面主要是簡單的來介紹委派的基礎功能
再來還有稍微進階一點的介紹
使用起來更順手

在隨著版本提升委派的宣告方式也越來越精簡
還有一種叫做匿名方式
請看下面CODING!

private void button7_Click(object sender, EventArgs e)
        {
            string ttttttt="";//存放答案用
            var TR1 = new TTO(GGGG);//傳統的建立方式 var則是取代TTO的物件
            //var得出現主要是來解決LINQ的問題個多請查略網路
            TTO TR2 = GGGG;//直接指定類別更直覺!
            TTO TR3 = delegate(string R) { return "MYNAME2:" + R; };//2.0新增的匿名方式
            //直接在delegate中建立類別
            TTO TR4 = N => "myNAME3:" + N;//利用Lambda更精簡了
            //之後讀取 輸出
            ttttttt += TR1("HI1") + "\n";//答案= MYNAME:HI1
            ttttttt += TR2("HI2") + "\n";//答案= MYNAME:HI2
            ttttttt += TR3("HI3") + "\n";//答案= MYNAME2:HI3
            ttttttt += TR4("HI4");//答案= myNAME:HI4
            MessageBox.Show(ttttttt);
            MessageBox.Show(TR1.Invoke("G"));//答案= MYNAME:G
            ////g0.Invoke(); 來引發,另一種是更為直覺的 g1(); 直接執行。
            MessageBox.Show(TR1("R"));//答案= MYNAME:R
        }

再來記錄更進階委派用法
利用累加+=來一個一個執行
比如我觸發事件後 可以同時 做動許多事情
來看一下範例 如下

private void button8_Click(object sender, EventArgs e)
        {
            var g0 = new B(printName);
            //第一次執行
            //g0先將參數傳入printName(s=,A print2Console)
            //然後p是委派物件到print2Console
            //在printName再次委派  p帶入摻數p(s=)
            // 而print2Console執行 s=+773
            // MESSAGESHOW出  S=733
            g0 += delegate(string n, A p) { p("OK:" + n); };
            //第二次執行 匿名法
            //一樣用P再次委派並帶入摻數+"ok"字串
            //p("ok:"+s=) 而p摻數是一個 ptint2Console
            //p("ok:"+s=) 傳入ptint2Console
            //將SHOW出  ok:s=733
            g0 += (n, p) => p("PP" + n);
            //第三次委派利用Lambda
            //一樣 再呼叫 ptint2Console之前
            //n多加一個PP字串,一並傳入ptint2Console
            //將SHOW出 PPs=773
            g0("s=", ptint2Console);//設定參數,注意ptint2Console指定給委派的方法
        }
        public delegate void A(string txt);
        public delegate void B(string n, A p);
        public void printName(string name, A p)
        {
            p(name);//p是ptint2Console
            //而name將傳入ptint2Console+733
        }
        public static void ptint2Console(string txt)
        {
            MessageBox.Show(txt + "773");
        }



在多程序中呼叫委派
在程序中可以呼叫外部程序

private void button9_Click(object sender, EventArgs e)
        {//建立多程序 並在程序START中呼叫委派
            Thread NewThread = new Thread(new ThreadStart(NewThreadMethod));
            NewThread.Start();//開始呼叫NewThreadMethod()
        }
        MyDelegate ShowData = new MyDelegate(Method);//委派指向好Method
        delegate void MyDelegate(int Param);//宣告委派帶摻數
        static void Method(int Param)
        {
            int i = Param;
           
            MessageBox.Show(i.ToString());
            //每2秒SHOW一次
        }
        void NewThreadMethod()
        {
            int i = 0;
            while (true)//無限迴圈運行中
            {//不斷呼叫Method並帶入參數
             this.Invoke(this.ShowData, i);//跨程序關鍵呼叫Method
                Thread.Sleep(2000);
            }
        }

沒有留言:

張貼留言