概念篇-委托和事件

本篇文章主要采用理论和代码实例相结合方式来论述委托和事件,涉及到一些边界技术,如软件架构的OCP原则(开-闭原则),

软件架构解耦,设计模式(Sender-Order)和事件驱动模型,有一定难度和深度,不适合初级者。

第一部份   委托

关于委托内容,主要围绕下图来论述。

一   委托是什么(what)

(一)委托产生的背景之一

1.我们先来假设这样一个情景需求:

设计一个系统,使其满足如下条件:

(1)当前,只有中国人和英国人使用该系统;

(2)向系统输入用户名和相应的语言,将产生相应语言的问候语;

(3)后期,可能会有其他国家语言加入该系统(系统变化的部分) ;

2.技术方案实现

关于技术方案实现,我们可以采用下图中的三种方式之一。

为了更好地叙述委托,我们分别实现三种技术方案,并找出它们的关系。

2.1 一般实现

Code(控制台程序)

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(GetGreetingContens("小王", "Chinese"));
            Console.WriteLine(GetGreetingContens("Alan_beijing", "English"));
            Console.WriteLine(GetGreetingContens("Linda", "Russian"));
            Console.Read();
        }

        //根据用户名和语言,获取问候语
        public static string GetGreetingContens(string UserName, string Language)
        {
            //New 一个GreetToUsers对象
            GreetToUsers greetToUsers = new GreetToUsers();
            //当然,你也可以使用switch开发语句来代替如下的if......else......
            if (Language == "Chinese")
            {
                return greetToUsers.ChinesePeople(UserName);
            }
            else if (Language == "English")
            {
                return greetToUsers.EnglishPeople(UserName);
            }
            else
            {
                return "抱歉,当前系统只支持汉语与英语(Sorry, the current system only supports Chinese and English.)";
            }
        }
    }

    //定义基本问候类和方法
    public class GreetToUsers
    {
        //Chinese People
        public string ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            return GreetContents;
        }

        //English People
        public string EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            return GreetContents;
        }
    }

}

Result

分析

2.2用接口实现

如上,我们分析了方案一中的问题,为了更好地解决方案一存在的问题,我们采用面向接口编程的形式来实现。

2.2.1  什么是面向接口编程?

面向接口编程,主要是解决软件架构设计中“动静问题”,即封装不变(静),剥离变化(抽出变化)。

Code:

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            GreetToChineseUsers greetToChinesUsers = new GreetToChineseUsers();
            GreetToEnglishUsers greetToEnglishUsers = new GreetToEnglishUsers();
            GreetToOtherUsers greetToOtherUsers = new GreetToOtherUsers();
            //Chinse Users
            IGreetToUsers iGreetToChineseUsers = greetToChinesUsers;
            Console.WriteLine(iGreetToChineseUsers.CountryPeople("小王", "Chinese"));
            //English Users
            IGreetToUsers iGreetToEnglishUsers = greetToEnglishUsers;
            Console.WriteLine(iGreetToEnglishUsers.CountryPeople("Alan_beijing", "English"));
            //Other Users
            IGreetToUsers iGreetToOtherUsers = greetToOtherUsers;
            Console.WriteLine(iGreetToOtherUsers.CountryPeople("Linda", "Russian"));

            Console.Read();
        }

    }

    //系统输出问候语(变化的部分,语言为变化因子)
    public interface IGreetToUsers
    {
        string CountryPeople(string UserName,string Language);
    }

    //汉语用户类
    public class GreetToChineseUsers:IGreetToUsers
    {
        //Chinese People
        public string  CountryPeople(string UserName, string Language)
        {
            string GreetContents = "您好!" + UserName;
            return GreetContents;
        }
    }

    //英语用户类
    public class GreetToEnglishUsers : IGreetToUsers
    {
        //English People
        public string CountryPeople(string UserName, string Language)
        {
            string GreetContents = "Hello," + UserName + "!";
            return GreetContents;
        }
    }

    //其他用户类
    public class GreetToOtherUsers : IGreetToUsers
    {
        //English People
        public string CountryPeople(string UserName, string Language)
        {
            return "Sorrry,当前系统只支持汉语与英语";
        }
    }

}

result

分析:

(1)如上,我们将变化因子"语言"剥离出来,形成接口,以后只要每增加一个语言,只需实现接口即可,满足了OCP原则,基本解决了方案一中存在的问题;

(2)如上代码只是为了演示面向接口编程这个功能,并不完善,感兴趣的读者,可自行完善(如将语言定义为枚举类型等);

方案二中的代码,细心的读者会发现,Main方法中new了三个对象,假若以后系统有300门语言,那岂不New 300个类,这样的话,也不利于代码维护呀,怎么解决这个问题呢?(提示一下,采用设计模式抽象工厂即可解决该问题)

2.3 用委托实现

在这里,没接触过委托的读者,先跳过这部分,往下读,看完(三)怎样使用委托(How to use)后,再来看本部分。

Code

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //根据语言判断,传递哪个方法的参数
            Console.WriteLine("------------请输入用户名------------");
            string UserName = Console.ReadLine();
            Console.WriteLine("------------请输入语言------------");
            string Language = Console.ReadLine();
            Console.WriteLine("------------输出结果------------");
            GreetToUsers greetToUsers = new GreetToUsers();
            if (Language == "Chinese")
            {
               Console.WriteLine(GetGreetingContents(UserName, greetToUsers.ChinesePeople));
            }
            else if (Language == "English")
            {
                Console.WriteLine(GetGreetingContents(UserName, greetToUsers.EnglishPeople));
            }
            else
            {
               Console.WriteLine(GetGreetingContents(UserName, greetToUsers.OtherPeople));
            }
           Console.Read();
        }

        public static string GetGreetingContents(string UserName,DelegateGetGreeting delegateGetGreeting)
        {
           return delegateGetGreeting(UserName);
        }
    }

    //定义委托
    public delegate string DelegateGetGreeting(string UserName);

    //定义基本问候类和方法
    public  class GreetToUsers
    {
        //Chinese People
        public string ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            return GreetContents;
        }

        //English People
        public string EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            return GreetContents;
        }
        //非英非汉
        public string OtherPeople(string UserName)
        {
            return "Sorrry,当前系统只支持汉语与英语";
        }
    }

}

Result

2.3 分析上述三种实现方案的关系

通过上诉三种方式的比较,我们容易得出委托的如下结论:

(1)抽象方法,屏蔽方法细节,调用只需传递方法名字即可;

(2)能够实现程序的解耦,松耦合(在方案一中,GetGreetingContens方法体内new了GreetToUsers对象,强耦合)

(3)委托一般扮演中间者的角色,这功能在委托事件中体现非常明显(第二部分 事件 将详细论述)

如我们在租房子时,可以直接找房东(技术实现的一般方法,强耦合,让租房者和房东直接联系),也可找中介(技术实现的委托,松耦合,租房者通过中介来与房东联系)

2.4 委托背景概述

委托的重要产生背景,就是事件驱动模型(关于什么是事件和事件驱动,在本文第二部份 事件 论述)。

(二) 委托定义

用delegate关键字定义委托(注意,委托是没有方法体的,类似接口里面的方法),在定义委托前,必须明确两个问题:

1.委托将要绑定的方法;

2.委托的形参类型,形参个数和委托的返回值必须与将要绑定的方法的形参类型,形参个数和返回值一致;

(三)相关概念

委托涉及的相关概念有函数指针,类型安全性、事件、Lambda表达式等

1.函数指针:在C++中,指针的一个类别,主要指向函数(变量指针,主要指向变量地址),可以把C#中的委托理解为函数指针;

2.类型安全性:在C++中,我们都知道指针是类型不安全的(返回值,返回类型和什么时候返回,这些都是未知的),而委托是类型安全的;

3.事件:可以把事件理解为委托的一种特例(在本文第二部份 事件 论述)

4.Lambda表达式:委托与Lambd表达式相结合,实现高效编程,与Jquery的“较少代码做更多的事”类似,委托与Lambda,Linq相结合,使较短代码就能实现比较复杂的功能(在本篇文章中不讲解Lambda与Lambda树,将在后续文章中讲解)

(四)委托组成

大致分为两部分:声明委托和注册方法(也叫绑定方法)

1.声明委托

用delegate声明;

2.绑定方法

绑定具体方法,传递方法名称;

(五) 委托种类

委托种类,一般分为多播委托和单播委托

1.单播委托:绑定单个方法

2.绑定多个方法

(六) 委托操作

1.绑定方法

2.解绑方法

二  委托能解决什么问题(Can do)

1.避免核心方法中存在大量的if....else....语句(或swich开关语句);

2.满足程序设计的OCP原则;

3.使程序具有扩展性;

4.绑定事件;

5.结合Lambda表达式,简化代码,高效编程;

6.实现程序的松耦合(解耦),这个在事件(event)中体现比较明显;

三  怎么使用委托(How to use)(本篇文章不谈匿名委托,匿名委托具体内容,将在Lambda章节讲解)

(一)委托的基本构成

通常地,使用委托的步骤与使用类的步骤是一样的。大致分为两步:定义委托和绑定方法(传递方法)

1.定义委托

用delegate关键字定义委托(注意,委托是没有方法体的,类似接口里面的方法),在定义委托前,必须明确两个问题:

(1).委托将要绑定的方法;

(2).委托的形参类型,形参个数和委托的返回值必须与将要绑定的方法的形参类型,形参个数和返回值一致;

public delegate  委托返回类型  委托名(形参)

例子:如上我们委托将要表示系统输出的问候语

a.委托将要绑定的方法

public string ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            return GreetContents;
        }

        //English People
        public string EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            return GreetContents;
        }
        //非英非汉
        public string OtherPeople(string UserName)
        {
            return "Sorrry,当前系统只支持汉语与英语";
        }

b.由如上方法可看出,方法的返回类型为string,方法有一个string类型的形参,在定义委托时,与其保持一致即可

//定义委托
public delegate string DelegateGetGreeting(string UserName);

2.绑定方法

使用委托时,将方法名字作为参数传递给委托即可

1 GreetToUsers greetToUsers = new GreetToUsers();
2 GetGreetingContents(UserName, greetToUsers.ChinesePeople)

(二)委托绑定方法

1.绑定单个方法

绑定单个方法,将单个方法名字传给委托即可

static void Main(string[] args)
        {
            //根据语言判断,传递哪个方法的参数
            Console.WriteLine("------------请输入用户名------------");
            string UserName = Console.ReadLine();
            Console.WriteLine("------------请输入语言------------");
            string Language = Console.ReadLine();
            Console.WriteLine("------------输出结果------------");
            GreetToUsers greetToUsers = new GreetToUsers();
            DelegateGetGreeting DGG;
            if (Language == "Chinese")
            {
                //绑定单个方法
                DGG = greetToUsers.ChinesePeople;
                Console.WriteLine(GetGreetingContents(UserName, DGG));
            }
            else if (Language == "English")
            {
                DGG = greetToUsers.EnglishPeople;
                Console.WriteLine(GetGreetingContents(UserName, DGG));
            }
            else
            {
                DGG = greetToUsers.OtherPeople;
                Console.WriteLine(GetGreetingContents(UserName, DGG));
            }

            Console.Read();
        }

另一种不太规范写法:不用GetGreetingContents(string UserName,DelegateGetGreeting delegateGetGreeting)方法

static void Main(string[] args)
        {
            //根据语言判断,传递哪个方法的参数
            Console.WriteLine("------------请输入用户名------------");
            string UserName = Console.ReadLine();
            Console.WriteLine("------------请输入语言------------");
            string Language = Console.ReadLine();
            Console.WriteLine("------------输出结果------------");
            GreetToUsers greetToUsers = new GreetToUsers();
            DelegateGetGreeting DGG;
            if (Language == "Chinese")
            {
                //绑定单个方法
                DGG = greetToUsers.ChinesePeople;
                Console.WriteLine(DGG(UserName));
            }
            else if (Language == "English")
            {
                DGG = greetToUsers.EnglishPeople;
                Console.WriteLine(DGG(UserName));
            }
            else
            {
                DGG = greetToUsers.OtherPeople;
                Console.WriteLine(DGG(UserName));
            }

            Console.Read();
        }

之所以不规范,主要是在项目中,不利于代码的模块化。

2.绑定多个方法(多播委托)

注意:绑定多个方法时,委托范围类型必须为void类型,否则只返回最后一个绑定的值。

绑定多个方法,采用 += 绑定

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            GreetToUsers greetToUsers = new GreetToUsers();
            DelegateGetGreeting DGG;

            //绑定多个方法
            DGG = greetToUsers.ChinesePeople;
            DGG += greetToUsers.EnglishPeople;
            DGG("小王");

            Console.Read();
        }

    }

    //定义委托
    public delegate void DelegateGetGreeting(string UserName);

    //定义基本问候类和方法
    public  class GreetToUsers
    {
        //Chinese People
        public void ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            Console.WriteLine(GreetContents);
        }

        //English People
        public void EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            Console.WriteLine(GreetContents);
        }
        //非英非汉
        public void OtherPeople(string UserName)
        {
            Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
        }
    }

}

3.解绑方法

解载绑定的方法,采用 -= 解绑

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            GreetToUsers greetToUsers = new GreetToUsers();
            DelegateGetGreeting DGG;

            //绑定多个方法
            DGG = greetToUsers.ChinesePeople;
            DGG += greetToUsers.EnglishPeople;

            //解绑ChinesePeople方法
            DGG-= greetToUsers.ChinesePeople;
            DGG("小王");

            Console.Read();
        }

    }

    //定义委托
    public delegate void DelegateGetGreeting(string UserName);

    //定义基本问候类和方法
    public  class GreetToUsers
    {
        //Chinese People
        public void ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            Console.WriteLine(GreetContents);
        }

        //English People
        public void EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            Console.WriteLine(GreetContents);
        }
        //非英非汉
        public void OtherPeople(string UserName)
        {
            Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
        }
    }

}

(三)委托机制

将如下代码通过反汇编工具.NET Reflector反汇编

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            GreetToUsers GTU = new GreetToUsers();

            DelegateGreet DG = new DelegateGreet();

            //DG.delegateGetGreeting = GTU.ChinesePeople;//注册方法
            DG.delegateGetGreeting += GTU.ChinesePeople;
            DG.delegateGetGreeting += GTU.EnglishPeople;
            DG.GreetUser("小王");

            Console.Read();
        }
    }

    public class DelegateGreet
    {
        //声明委托
        public delegate void DelegateGetGreeting(string UserName);

        //委托变量为public,破坏了类的封装性
        public DelegateGetGreeting delegateGetGreeting;

        //虽然Event论定义为public,但其还是私有变量,只能通过+=,或-=访问
        //public event DelegateGetGreeting EventGreet;

        public void GreetUser(string UserName)
        {
            //EventGreet?.Invoke(UserName);
            delegateGetGreeting(UserName);
        }
    }

    //定义基本问候类和方法
    public class GreetToUsers
    {
        //Chinese People
        public void ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            Console.WriteLine(GreetContents);
        }

        //English People
        public void EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            Console.WriteLine(GreetContents);
        }
        //非英非汉
        public void OtherPeople(string UserName)
        {
            Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
        }
    }
}

反汇编

分析:

1.三个核心方法:BeginInvoke,EndInvoke和Invoke

(1)使用Invoke完成一个委托方法的封送,就类似于使用SendMessage方法来给界面线程发送消息,是一个同步方法。也就是说在Invoke封送的方法被执行完毕前,Invoke方法不会返回,从而调用者线程将被阻塞。

(2使用BeginInvoke方法封送一个委托方法,类似于使用PostMessage进行通信,这是一个异步方法。也就是该方法封送完毕后马上返回,不会等待委托方法的执行结束,调用者线程将不会被阻塞。但是调用者也

可以使用EndInvoke方法或者其它类似WaitHandle机制等待异步操作的完成。

总结:但是在内部实现上,Invoke和BeginInvoke都是用了PostMessage方法,从而避免了SendMessage带来的问题。而Invoke方法的同步阻塞是靠WaitHandle机制来完成的。

提示:

最近浏览一篇文章,也讲得不错:http://blog.csdn.net/goodshot/article/details/6157529

要想深入了解,请参照《CLR Via C#》,

第二部分  事件

关于事件(event),将会从如下四个角度来分析.

1.什么是事件

2.事件能解决什么问题

3.怎么使用事件

4.事件机制

一  什么是事件

谈到委托,必提事件,事件本质是对委托的封装,对外提供add_EventName(对应+=)和remove_EventName(对应-=)访问,从而实现类的封装性。

1.种类

强类型事件和弱类型事件

2.一些用处

(1)WebForm控件的Click事件。做过WebForm开发的朋友,可能对事件是非常熟悉的,如拖一个Button,双击,就自动在后台生成Button的Click事件,如下图所示。

原理:在Windows运用程序中,Button类提供了Click事件,其本质就是委托,当我们触发Click事件时,调用的处理程序方法需要参数,其参数就是由委托类型来定义的。

(2)设计模式发布/订阅。事件是基于委托的,为委托提供了一种发布/订阅机制。

二 事件能解决哪些问题

1.将公有的委托变量定义为私有变量,从而满足类的封装性原则;

2.具有委托具有的作用;

三 如何使用事件

1.声明委托

public delegate void DelegateGetGreeting(string UserName);

2.声明事件

与委托声明一样,只不过多了一个关键字event

public event DelegateGetGreeting EventGreet;

3.时间注册方法

事件注册方法与委托注册方法是一样的。

1 DelegateGreet DG= new DelegateGreet();
2 //DG.delegateGetGreeting = GTU.ChinesePeople;//注册方法
3 DG.EventGreet+= GTU.ChinesePeople;
4 DG.EventGreet += GTU.EnglishPeople;

4.调用事件

调用定义事件的方法

DG.GreetUser("小王");

完整代码如下:

using System;

namespace DelegateDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            GreetToUsers GTU = new GreetToUsers();

            DelegateGreet DG= new DelegateGreet();

            //DG.delegateGetGreeting = GTU.ChinesePeople;//注册方法
            DG.EventGreet+= GTU.ChinesePeople;
            DG.EventGreet += GTU.EnglishPeople;
            DG.GreetUser("小王");

            Console.Read();

        }

    }
    public class DelegateGreet
    {
        //声明委托
        public delegate void DelegateGetGreeting(string UserName);

        //委托变量为public,破坏了类的封装性
        //public DelegateGetGreeting delegateGetGreeting;

        //虽然Event论定义为public,但其还是私有变量,只能通过+=,或-=访问
        public event DelegateGetGreeting EventGreet;

        public void GreetUser(string UserName)
        {
            EventGreet?.Invoke(UserName);
            //delegateGetGreeting(UserName);
        }

    }

    //定义基本问候类和方法
    public  class GreetToUsers
    {
        //Chinese People
        public void ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            Console.WriteLine(GreetContents);
        }

        //English People
        public void EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            Console.WriteLine(GreetContents);
        }
        //非英非汉
        public void OtherPeople(string UserName)
        {
            Console.WriteLine("Sorrry,当前系统只支持汉语与英语");
        }
    }

}

四 事件机制

事件的本质就是委托,向外提供两个访问方法add_EventName(对应+=)和remove-EventName(对应-=),我们通过.NET Reflector反汇编工具来查看,到底是不是这样的。

参考文献

【01】C#高级编程(第七版)  (Christian Nagel,Bill Evjen和Jay Glynn 编著,李铭 译,黄静 审校)

本篇文章主要采用理论和代码实例相结合方式来论述委托和事件,涉及到一些边界技术,如软件架构的OCP原则(开-闭原则),

软件架构解耦,设计模式(Sender-Order)和事件驱动模型,有一定难度和深度,不适合初级者。

第一部份   委托

关于委托内容,主要围绕下图来论述。

一   委托是什么(what)

(一)委托产生的背景之一

1.我们先来假设这样一个情景需求:

设计一个系统,使其满足如下条件:

(1)当前,只有中国人和英国人使用该系统;

(2)向系统输入用户名和相应的语言,将产生相应语言的问候语;

(3)后期,可能会有其他国家语言加入该系统(系统变化的部分) ;

2.技术方案实现

关于技术方案实现,我们可以采用下图中的三种方式之一。

为了更好地叙述委托,我们分别实现三种技术方案,并找出它们的关系。

2.1 一般实现

Code(控制台程序)

 

Result

分析

2.2用接口实现

如上,我们分析了方案一中的问题,为了更好地解决方案一存在的问题,我们采用面向接口编程的形式来实现。

2.2.1  什么是面向接口编程?

面向接口编程,主要是解决软件架构设计中“动静问题”,即封装不变(静),剥离变化(抽出变化)。

Code:

 

result

分析:

(1)如上,我们将变化因子"语言"剥离出来,形成接口,以后只要每增加一个语言,只需实现接口即可,满足了OCP原则,基本解决了方案一中存在的问题;

(2)如上代码只是为了演示面向接口编程这个功能,并不完善,感兴趣的读者,可自行完善(如将语言定义为枚举类型等);

方案二中的代码,细心的读者会发现,Main方法中new了三个对象,假若以后系统有300门语言,那岂不New 300个类,这样的话,也不利于代码维护呀,怎么解决这个问题呢?(提示一下,采用设计模式抽象工厂即可解决该问题)

2.3 用委托实现

在这里,没接触过委托的读者,先跳过这部分,往下读,看完(三)怎样使用委托(How to use)后,再来看本部分。

Code

 

Result

2.3 分析上述三种实现方案的关系

通过上诉三种方式的比较,我们容易得出委托的如下结论:

(1)抽象方法,屏蔽方法细节,调用只需传递方法名字即可;

(2)能够实现程序的解耦,松耦合(在方案一中,GetGreetingContens方法体内new了GreetToUsers对象,强耦合)

(3)委托一般扮演中间者的角色,这功能在委托事件中体现非常明显(第二部分 事件 将详细论述)

如我们在租房子时,可以直接找房东(技术实现的一般方法,强耦合,让租房者和房东直接联系),也可找中介(技术实现的委托,松耦合,租房者通过中介来与房东联系)

2.4 委托背景概述

委托的重要产生背景,就是事件驱动模型(关于什么是事件和事件驱动,在本文第二部份 事件 论述)。

(二) 委托定义

用delegate关键字定义委托(注意,委托是没有方法体的,类似接口里面的方法),在定义委托前,必须明确两个问题:

1.委托将要绑定的方法;

2.委托的形参类型,形参个数和委托的返回值必须与将要绑定的方法的形参类型,形参个数和返回值一致;

(三)相关概念

委托涉及的相关概念有函数指针,类型安全性、事件、Lambda表达式等

1.函数指针:在C++中,指针的一个类别,主要指向函数(变量指针,主要指向变量地址),可以把C#中的委托理解为函数指针;

2.类型安全性:在C++中,我们都知道指针是类型不安全的(返回值,返回类型和什么时候返回,这些都是未知的),而委托是类型安全的;

3.事件:可以把事件理解为委托的一种特例(在本文第二部份 事件 论述)

4.Lambda表达式:委托与Lambd表达式相结合,实现高效编程,与Jquery的“较少代码做更多的事”类似,委托与Lambda,Linq相结合,使较短代码就能实现比较复杂的功能(在本篇文章中不讲解Lambda与Lambda树,将在后续文章中讲解)

(四)委托组成

大致分为两部分:声明委托和注册方法(也叫绑定方法)

1.声明委托

用delegate声明;

2.绑定方法

绑定具体方法,传递方法名称;

(五) 委托种类

委托种类,一般分为多播委托和单播委托

1.单播委托:绑定单个方法

2.绑定多个方法

(六) 委托操作

1.绑定方法

2.解绑方法

二  委托能解决什么问题(Can do)

1.避免核心方法中存在大量的if....else....语句(或swich开关语句);

2.满足程序设计的OCP原则;

3.使程序具有扩展性;

4.绑定事件;

5.结合Lambda表达式,简化代码,高效编程;

6.实现程序的松耦合(解耦),这个在事件(event)中体现比较明显;

三  怎么使用委托(How to use)(本篇文章不谈匿名委托,匿名委托具体内容,将在Lambda章节讲解)

(一)委托的基本构成

通常地,使用委托的步骤与使用类的步骤是一样的。大致分为两步:定义委托和绑定方法(传递方法)

1.定义委托

用delegate关键字定义委托(注意,委托是没有方法体的,类似接口里面的方法),在定义委托前,必须明确两个问题:

(1).委托将要绑定的方法;

(2).委托的形参类型,形参个数和委托的返回值必须与将要绑定的方法的形参类型,形参个数和返回值一致;

原文地址:https://www.cnblogs.com/dongh/p/8439280.html

时间: 2024-08-30 05:39:22

概念篇-委托和事件的相关文章

对张子扬显示的两篇委托和事件说得很透文章读后的思考

第一篇 C#中的委托和事件 http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx 第二篇 C#中的委托和事件(续) http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-Advanced.aspx 这是两篇目前为止,我读过的介绍委托和事件以及异步调用最简明清晰文章,作者通过非常有节奏的"标题"->&q

C#委托与事件学习笔记

今天跟随视频学习了一下C#中最重要的一些概念之委托与事件.老杨的视频讲的还是挺深入浅出,不过刚接触C#.NET的人还是朦朦胧胧,就像张子阳先生说的"每次见到委托和事件就觉得心里别(biè)得慌,混身不自在".跨过这道坎的人就有种一览众山小的感觉了.我又浏览了皱华栋老师JamesZou的博文<深入理解C#委托及原理>(地址:http://www.cnblogs.com/jameszou/archive/2011/07/21/2112497.html),以及张子阳Jimmy Z

对张子阳先生对委托和事件的两篇文章的读后思考(说得很透,内附故事一篇)

第一篇 C#中的委托和事件 第二篇 C#中的委托和事件(续) 首先,张子阳先生的这是两篇关于委托和事件间关系的文章,是目前为止我读过的介绍委托和事件以及异步调用最简明清晰文章,作者通过非常有节奏的"标题"->"问题"->"思路"->"实现"->"讲解"的结构,分步骤一步一步地将委托和事件的实现.应用与原理阐述得非常清楚,并且在行文期间将自己有趣的思考过程通过生动的语言表达了出来,使人

c# 委托和事件(总结篇)

c# 委托和事件(总结篇) 概念: delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类.与其它的类不同,delegate类能够 拥有一个签名(signature),并且它"只能持有与它的签名相匹配的方法的引用".它所实现的功能与C/C++中的函数指针 十分相似.它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m.但与函数指针相比, delegate有许多函数委托和事件在 .Net Framework中的应用非常广泛指针不具备的优

C#基础加强篇—委托、Lambda表达式和事件(下)

3.事件 事件作为C#中的一种类型,为类和类的实例定义发出通知的能力,从而将事件和可执行代码捆绑在了一起.事件是对象发送的消息,以发信号通知操作的发生.操作可能是由用户交互引起的,也可能是由某些其他的程序逻辑触发的.引发(触发)事件的对象叫做事件发送方,捕获事件并对其做出响应的对象叫做事件接收方. C#事件是按“发布——预定”的方式工作.先在一个类中公布事件,然后就可以在任意数量的类中对事件预定.在事件通信中,事件发送方类并不知道哪个对象或方法将接收到(处理)它所引发的事件.所需要的是在源和接收

[转载]C#深入分析委托与事件

原文出处: 作者:风尘浪子 原文链接:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html 同类链接:http://www.cnblogs.com/SkySoot/archive/2012/04/05/2433639.html 引言 本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C# 当中事件(Event)的由来,它能使处理委托类型的过程变得更加简单.还将为您解释委托的协变与逆变,以及如何使用 Deleg

C#综合揭秘——深入分析委托与事件

本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C# 当中事件(Event)的由来,它能使处理委托类型的过程变得更加简单.还将为您解释委托的协变与逆变,以及如何使用 Delegate 使 Observer(观察者)模式的使用变得更加简单.在事件的介绍上,会讲述事件的使用方式,并以ASP.NET的用户控件为例子,介绍一下自定义事件的使用.最后一节,将介绍Predicate<T>.Action<T>.Func<T,TResult>多种泛型委托的使用和Lamb

浅谈委托和事件(一)

浅谈委托和事件(一) 关于委托和事件,可能是.NET或者说是面向对象编程语言中的一个比较重要又比较难以理解的概念.关于这一话题,园子里的人也写了很多文章,最经典的可能就是张子阳的C#中的委托和事件这两篇文章了,之前也看过MSDN 上的WebCast深入 "委托和事件".可能和很多人一样,刚开始读的时候,觉得很清楚,但是过了一段时间好像又忘记了委托和事件的区别,知道很久以前,在一次面试中我被问到委托和事件有什么区别,一下子就说不清了. 所以这里稍微理一下,也算是自己的一个总结.当然,还是

c#委托、事件、Observer

委托和事件在.NET Framework[1] 中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易. 中文名 委托 外文名 Delegate 编程语言 C# 作    用 方便的引用被委托的方法 目录 1引言 2参数 3委托 4由来 5编译代码 6设计模式 ? 范例说明 ? 模式简介 7委托事件 1引言编辑 c#委托和事件它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里憋得慌,浑身不自在.本文中,我将通过两个范例由浅