`

C#委托事件

    博客分类:
  • C#
阅读更多

Delegate 是在.NET1.0 的时候就已经存在了的特性,因为在准备总结Lambda 表达式的时候发现自己对Delegate 还没有深刻的理解,所以打算先对Delegate 进行整理一下。

       Delegate 中文译为“委托”,MSDN 中对Delegate 是这样进行解释的“C# 中的委托 类似于CC++ 中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内 。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与CC++ 中的函数指针不同,委托是面向对象、类型安全的,并且是安全的 。”

       我们来通过一个Demo 来进行理解:

class Program

    {

        static void OtherClassMethod()

        {

            Console .WriteLine("Delegate an other class's method" );

        }

        static void Main(string [] args)

        {

            var test = new TestDelegate ();

            test.delegateMethod = new TestDelegate .DelegateMethod (test.NonStaticMethod);

             test.delegateMethod += new TestDelegate .DelegateMethod (TestDelegate .StaticMethod);

            test.delegateMethod += Program .OtherClassMethod;

            test.RunDelegateMethods();

            Console .ReadKey();

        }

    }

  class TestDelegate

    {

        // 声明了一个Delegate 类型名为DelegateMethod ,这种Delegate 类型可以搭载返回值为void ,无参函数

        public delegate void DelegateMethod ();

        // 声明了一个Delegate 对象,注意一个是类型,一个是对象

        public DelegateMethod delegateMethod; 

        public static void StaticMethod()

        {

            Console .WriteLine("Delegate a static method" );

        }

        public void NonStaticMethod()

        {

            Console .WriteLine("Delegate a non-static method" );

        }

        public void RunDelegateMethods()

        {

            if (delegateMethod != null )

            {

                Console .WriteLine("---------------------" );

                delegateMethod.Invoke();

                Console .WriteLine("---------------------" );

            }

       }

    }

通过:

   test.delegateMethod = new TestDelegate .DelegateMethod (test.NonStaticMethod);

   test.delegateMethod += new TestDelegate .DelegateMethod (TestDelegate .StaticMethod);

   test.delegateMethod += Program .OtherClassMethod;

 

我们可以发现 delegateMethod 搭载了3 个函数(通过+= 增加搭载的函数,也可以通过-= 来去掉Delegate 中的某个函数),而且通过delegateMethod.Invoke() 运行被搭载的函数,这就是Delegate 可以看作为函数指针的原因。而在Java 中没有委托机制,如果向要实现此功能个人感觉只有通过Java 的内部类来实现。

       既然C# 中的委托与C++ 中函数指针如此相似,那么我简单整理一下Delegate 与函数指针的区别:

1、 一个delegate 对象一次可以搭载多个方法,而不是一次一个。当我们唤起一个搭载多个方法的delegate ,所有方法以开始被搭载到delegate 对象的顺序依次被唤起;

2、 一个delegate 对象所搭载的方法并不需要属于同一个类别,一个delegate 对象所搭载的所有方法必须具有与声明时相同的原型和形式,然而这些方法可以有static 也可以有non-static ,可以由一个或多个不同类别的成员组成;

3、 一个delegate type 的声明在本质上是创建了一个新的subtype instance ,该 subtype 派生自 .NET library framework abstract base classes Delegate MulticastDelegate ,它们提供一组public methods 用以询访delegate 对象或其搭载的方法(methods ) ,与函数指针不同,委托是面向对象、类型安全并且安全的。

 

Delegate 的使用场景:

首先先看下面这段代码

  class Program

    {

        static void Main(string [] args)

        {

            var car = new Car (15);

            new Alerter (car);

            car.Run(120);

            Console .ReadKey();

        }

        class Car

        {

            public delegate void Notify (int value);

             public event Notify notifier;

            private int petrol = 0;

            public int Petrol

            {

                get { return petrol; }

                set

                {

                    petrol = value ;

                    if (petrol < 10)  // petrol 的值小于10 时出发警报

                    {

                        if (notifier != null )

                        {

                            notifier.Invoke(Petrol);

                        }

                    }

                }

            }

            public Car(int petrol)

            {

                Petrol = petrol;

            }

            public void Run(int speed)

            {

                int distance = 0;

                while (Petrol > 0)

                 {

                    Thread .Sleep(500);

                    Petrol--;

                    distance += speed;

                    Console .WriteLine("Car is running... Distance is " + distance.ToString());

                }

            }

        }

        class Alerter

        {

            public Alerter(Car car)

            {

                car.notifier += new Car .Notify (NotEnoughPetrol);

            }

            public void NotEnoughPetrol(int value)

            {

                Console .ForegroundColor = ConsoleColor .Red;

                Console .WriteLine("You only have " + value.ToString() + " gallon petrol left!" );

                Console .ResetColor();

            }

        }

    }

 

通过上面的代码,你可能会有这样的疑问,为什么不再public in Petrol 中直接调用Alerter.NotEnoughtPetrol 呢?因为Car 模块和Alerter 模块本身是两个独立的子系统,如果直接调用,则程序的耦合性就会增加,这是程序员的大忌。

       其实上面的代码是设计模式中的观察者设计模式 的实现,当汽车在运行中汽油量<10 时,就会发出警报,在上面的代码中Delegate 相当于一个存放回调函数的函数指针,使用Delegate ,我们可以非常方便地实现观察者模式。而其实,在需要使用回调函数时,我们都可以考虑使用Delegate

下面我再举个例子吧,取生活中一个场景来说,孩子饿了,要哭,爸爸妈妈听到哭声都会赶过来。如果按照常规的编程方法,我们可能要在Child 类里边实现一个方法来通知爸爸和妈妈,假设有一天这家聚会,爷爷奶奶,姥姥姥爷,姑姑婶婶全过来了,那么孩子必须要通知增加的这些人,我们就不得不修改Child 类里的这个方法。而事实上我们可以这样考虑,将对孩子哭这一事件关心的一类人抽象出来,爷爷奶奶,姥姥姥爷,姑姑婶婶都从该类派生,他们有一个公共的代理,只要他们将自己的行为“注册”到这个代理,孩子一哭,所有被注册进去的事件就会形成一个事件的链表然后顺次执行。在这种模式下Child 类和Observer 类的派生类之间的耦合性大大降低了,我们不需要对Child 类的方法进行任何的修改而只需要讲Observer 类的派生类的各个实例对象对“孩子哭”这一事件的响应注册到“孩子哭”中就可以了。

class Program

    {

         public delegate void EventHandle (object sender, EventArgs e);

        class Entry

        {

            public static void Main()

            {

                Woman woman = new Woman ();

                Man man = new Man ();

                Child child = new Child ();

                child.call += new EventHandle (woman.observer_call);

                child.call += new EventHandle (man.observer_call);

                child.observer_call(null , null );

                Console .ReadKey();

            }

        }

        abstract class observer

        {

            public event EventHandle call;

           public void Subto(observer ob)

            {

                this .call += new EventHandle (ob.observer_call);

            }

            abstract public void observer_call(object sender, EventArgs e);

            public void Shout()

            {

                if (call != null )

                {

                    call(this , null );

                }

            }

        }

        class Woman : observer

         {

            public override void observer_call(object sender, EventArgs e)

            {

                Console .WriteLine("Woman : Oh Baby, mom is coming!" );

                Shout();

            }

        }

        class Man : observer

        {

            public override void observer_call(object sender, EventArgs e)

            {

                Console .WriteLine("Man : Oh Baby, papa is coming!" );

                Shout();

            }

        }

        class Child : observer

        {

            public override void observer_call(object sender, EventArgs e)

            {

                Console .WriteLine("Child : Where are my parents? I'm hungry!" );

                Shout();

            }

        }

    }

 

上面我定义了一个委托,它的作用是将被委托的函数以参数形式“传递”给事件,从而构成一个事件的链表。

       说明,委托在编译的时候会编译成类,因为委托是一个类,所以在任何可以声明类的地方都可以声明委托。它定义了方法的类型,使得可以将方法当作另一个方法的参数传递,这种将方法动态的赋给参数的做法,可以避免在程序中大量地使用if else(switch) 语句,同时使得程序具有更好的扩展性;

 

       在上面的“   public event Notify notifier; ”可以改写为“   public Notify notifier; ”这就是我下面需要整理的DelegateEvent

 

Delegate Event

       通过项目发现很多时候DelegateEvent 这两个关键字经常会在一起使用,那两者之间是什么关系呢?通过msdn 的解释是“声明事件:若要在类内声明事件,首先必须声明该事件的委托类型”

  • 大小: 15.3 KB
  • 大小: 5.3 KB
分享到:
评论

相关推荐

    c#委托事件异步例子

    在C#编程中,委托和事件是两种非常重要的特性,它们是实现面向对象设计的关键工具,尤其是对于构建异步应用程序。下面将详细讲解这两个概念及其在异步编程中的应用。 一、委托 委托在C#中可以被视为一种类型,它...

    C#委托事件实例

    在C#编程语言中,委托和事件是两个关键特性,它们...总的来说,理解和掌握C#的委托事件对于任何想要深入学习.NET框架的开发者来说都是至关重要的。通过实例学习,初学者和进阶者都能从中受益匪浅,提升自己的编程技能。

    net资料--C#委托事件

    C#委托事件C#委托事件C#委托事件C#委托事件C#委托事件C#委托事件

    计算机课程设计C#委托事件

    计算机课程设计C#委托事件 通过分析给定的文件信息,我们可以生成以下知识点: 1. 什么是事件?事件是类在发生其关注的事情时用来提供通知的一种方式。事件的发生一般都牵扯2个角色:事件发行者(Publisher)和...

    C# 委托 线程 事件的事例代码

    在C#编程中,委托、线程和事件是三个核心概念,它们对于构建高效、响应式的多任务应用程序至关重要。下面将详细阐述这三个概念及其相互之间的关系,并通过一个实例代码进行说明。 1. 委托(Delegate): 委托在C#中...

    C#--委托和事件

    ### C#中的委托和事件 #### 一、委托的基础概念 在C#中,委托是一种引用类型的数据结构,它允许将方法当作参数进行传递。简而言之,委托就是指向一个方法的引用。委托的主要用途是作为事件处理程序的类型。 **...

    详解C#委托,事件与回调函数

    详解 C# 委托、事件与回调函数 委托是 C# 中一种非常重要的概念,它可以将方法作为参数传递给其他方法,也可以将方法作为返回值返回给其他方法。委托的定义是:delegate 返回类型 委托名(参数列表);例如:...

    C# 委托事件简单的使用例子

    这是C# 委托与事件简单的使用例子。 只是为了初学者更好的接受委托与事件使用方法而已。 程序有两个窗体,一个是主窗体,一个是副窗体。 打开主窗体,在主窗体中点按钮后,打开副窗体,在副窗体中,可以调整主窗体...

    C#委托事件.zip

    在C#编程语言中,委托和事件是两个关键的概念,它们是实现面向对象设计模式,尤其是事件驱动编程的基础。本文将深入探讨这两个概念,并通过实例代码来帮助初学者理解和掌握。 **一、委托** 委托在C#中可以看作是...

    c#委托事件的实现

    基于c#程序对c语言中的委托事件进行详细的分析与讲解

    C#中事件委托订阅发布模式

    在C#编程中,事件委托和订阅发布模式是核心特性之一,它们对于构建可扩展、模块化和松耦合的应用程序至关重要。事件是类之间通信的一种机制,它允许一个对象(发布者)通知其他对象(订阅者)某些特定操作的发生,而...

    C#委托事件详解

    本文将深入讲解C#委托及其在实际编程中的应用。 首先,让我们了解什么是委托。在C#中,委托可以被看作是一种类型,这种类型能够引用具有相同签名的方法。签名包括方法的返回类型和参数列表。委托类是.NET框架提供的...

    C# 委托 事件 专讲

    在C#编程语言中,委托和事件是两个非常重要的概念,它们构成了事件驱动编程的基础。本文将深入探讨这两个概念,以及它们在实际开发中的应用。 首先,我们来理解什么是委托。在C#中,委托是一种类型,它代表了方法的...

    C# 委托和事件 (详细讲解)

    在C#编程语言中,委托和事件是两个关键的概念,它们是实现面向对象设计模式,尤其是事件驱动编程的核心。下面将详细阐述这两个概念及其在实际编程中的应用。 **委托** 委托在C#中相当于一种类型,它封装了指向方法...

    C#中委托与事件的区别

    委托(Delegate)和事件(Event)是C#中非常重要的两种机制,它们在.NET框架中扮演着极其重要的角色。理解这两种概念,对于深入学习C#编程语言,构建高效、可维护的程序架构至关重要。首先我们来探讨一下委托的概念...

    c#多线程利用委托更新控件内容

    例如,在串口接收事件中,可以使用委托(delegate)来更新控件内容: `SetText(ASCIIEncoding.ASCII.GetString(arr));` 在上面的代码中,`arr` 是 byte[] 类型的数据,用于传递给控件内容更新方法。 使用委托...

Global site tag (gtag.js) - Google Analytics