程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 委托、Lambda表達式、事件系列06,使用Action實現觀察者模式,體驗委托和事件的區別,lambdaaction

委托、Lambda表達式、事件系列06,使用Action實現觀察者模式,體驗委托和事件的區別,lambdaaction

編輯:C#入門知識

委托、Lambda表達式、事件系列06,使用Action實現觀察者模式,體驗委托和事件的區別,lambdaaction


在"實現觀察者模式(Observer Pattern)的2種方式"中,曾經通過接口的方式、委托與事件的方式實現過觀察者模式。本篇體驗使用Action實現此模式,並從中體驗委托與事件的區別。

 

□ 使用Action實現觀察者模式

 

就舉一個足球場上的例子,當裁判吹響終場哨,勝隊慶祝,失敗隊落寞。把裁判看作是被觀察者,比賽中的兩隊看作是觀察者。

 

裁判作為被觀察者需要提供一個Action委托供觀察者方法注冊。

    public class Referee
    {
        public Action DoSth;
        public void ISayGameOver()
        {
            Console.WriteLine("嘀嘀嘀......比賽結束了~~");
            DoSth();
        }
    }

 

勝利的隊和失敗的隊擁有共同的基類。

    public class Team
    {
        private string _name;
        public Team(string name)
        {
            _name = name;
        }
        public string Name
        {
            get { return _name; }
        }
    }

 

勝利隊或失敗隊,作為觀察者,必須有符合Referee中Action定義的方法。

    public class WinTeam : Team
    {
        public WinTeam(string name) : base(name){}
        public void Celebrate()
        {
            Console.WriteLine("我們晉級了,好開心!");
        }
    }
    public class LoseTeam : Team
    {
        public LoseTeam(string name) : base(name){}
        public void WeAreSad()
        {
            Console.WriteLine("比賽輸了,好傷心!");
        }
    }

 

客戶端,先把失敗隊和勝利隊的方法注冊到Action變量,然後由被觀察者的一個方法觸發委托鏈和方法。

        static void Main(string[] args)
        {
            Referee referee = new Referee();
            var winTeam = new WinTeam("勝利隊");
            var loseTeam = new LoseTeam("失敗隊");
            //注冊觀察者
            referee.DoSth += winTeam.Celebrate;
            referee.DoSth += loseTeam.WeAreSad;
            //被觀察者啟動事件通知觀察者
            referee.ISayGameOver();
        } 

 

□ 體驗委托與事件的區別

 

現在,我們在客戶端,在調用Referee的實例方法ISayGameOver之前,嘗試把Referee的委托變量DoSth設置為null。

        static void Main(string[] args)
        {
            Referee referee = new Referee();
            var winTeam = new WinTeam("勝利隊");
            var loseTeam = new LoseTeam("失敗隊");
            //注冊觀察者
            referee.DoSth += winTeam.Celebrate;
            referee.DoSth += loseTeam.WeAreSad;
            referee.DoSth = null;
            //被觀察者啟動事件通知觀察者
            referee.ISayGameOver();
        }


可見,當把把Referee的委托變量DoSth設置為null後,所有注冊的方法將得不到執行。

 

如果把Referee的委托變量DoSth修飾為事件。

    public class Referee
    {
        public event Action DoSth;
        public void ISayGameOver()
        {
            Console.WriteLine("嘀嘀嘀......比賽結束了~~");
            if (DoSth != null)
            {
                DoSth();
            }
            
        }
    }


可見,當把委托變量DoSth修飾為事件後,只能通過+=和-=注冊、取消方法,不能通過=設置。

 

把referee.DoSth = null;注釋掉,將不會報錯。  

 

“委托、Lambda表達式、事件系列”包括:

委托、Lambda表達式、事件系列01,委托是什麼,委托的基本用法,委托的Method和Target屬性

委托、Lambda表達式、事件系列02,什麼時候該用委托

委托、Lambda表達式、事件系列03,從委托到Lamda表達式

委托、Lambda表達式、事件系列04,委托鏈是怎樣形成的, 多播委托, 調用委托鏈方法,委托鏈異常處理

委托、Lambda表達式、事件系列05,Action委托與閉包

委托、Lambda表達式、事件系列06,使用Action實現觀察者模式,體驗委托和事件的區別


C# 中怎利用lambda實現委托事件的掛接

委托定義如下:復制代碼 代碼如下:public class SocketSp{public delegate void ReceiveCompleted(byte[] receiveBuffer, int receiveTotalLen,Exception ex);public ReceiveCompleted receiveCompleted;}掛接方定義如下復制代碼 代碼如下:public class LinkOuter{SocketSp linkOuterSocket = new SocketSp();private void test(Socket requestHandleSocket){//此處要掛接 linkOuterSocket.receiveCompleted 事件,同時想將參數requestHandleSocket傳入,以便後續處理。}}第一個想法是利用delegate,但是失敗了。因為雖然掛接上去了,委托傳進的參數丟了,無法進行後續操作。復制代碼 代碼如下:private void test(Socket requestHandleSocket){linkOuterSocket.receiveCompleted += delegate {//To do};}第二個想法是利用Action,結果也失敗了。IDE提示委托Action未采用3個參數。復制代碼 代碼如下:private void test(Socket requestHandleSocket){linkOuterSocket.receiveCompleted += (Action)((outerReceiveBuffer, totalLen, ex) => {//To do});}第三個想法是利用lambda表達式,先與委托掛接,同時利用局部變量的調用,來實現參數傳遞到sendResponse函數中,以便後續操作。復制代碼 代碼如下:private void test(Socket requestHandleSocket){linkOuterSocket.receiveCompleted += new SocketSp.ReceiveCompleted((outerReceiveBuffer,totalLen,ex) =>{byte[] realOuterReceiveBuffer = new byte[totalLen];Array.Copy(outerReceiveBuffer, 0, realOuterReceiveBuffer, 0, totalLen);sendResponse(requestHandleSocket, realOuterReceiveBuffer,"200 OK", "text/html");});}最終用lambda表達式實現了。您可能感興趣的文章:C#用Lambda和委托實現模板方法
 

助C#中的lambda表達式與Action

new Action(
() => WatchOutput.Items.Insert(
0,string.Format(formatString,parameters)))
可以看作是:
void Action1()
{
WatchOutput.Items.Insert(
0,string.Format(formatString,parameters))
}
匿名委托的好處就是,可以直接使用方法內的變量,比如formatString和parameters。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved