zoukankan      html  css  js  c++  java
  • C#一些知识点:委托和事件的区别

    在C#中,委托和事件是比较容易混淆的两个知识点,本篇博客就记录一下委托和事件之间的区别。

    定义上的区别

    委托:委托实际上是一个类,用来表示一个函数,可以理解为C++中的函数指针。

    事件:事件是一个修饰符,用来修饰一个委托类型的属性,表示该委托的部分功能被限制了。

    我们可以这么理解:委托是类,定义了委托后,就可以像使用类一样的来使用这个委托,而事件修饰了委托后则是表示限制这个委托的部分功能,使其满足作为事件的规则。

    那么事件究竟限制了委托的什么功能呢?主要是下面的这两个限制:

    调用的限制

    委托的调用没有限制,可以在任意的地方进行调用,而事件修饰过的委托只能在定义自己的类中进行调用(注意连子类都不允许调用),如下:

     1 using System;
     2 
     3 namespace Study
     4 {
     5     class Program
     6     {
     7         static void Main(string[] args)
     8         {
     9             new App();
    10 
    11             Console.Read();
    12         }
    13     }
    14 
    15     public delegate void Foo();
    16 
    17     public class Test
    18     {
    19         public Foo foo1;
    20 
    21         public event Foo foo2;
    22 
    23         public Test()
    24         {
    25             foo1 += Func;
    26             foo1();
    27 
    28             foo2 += Func;
    29             foo2();
    30         }
    31 
    32         public void Func()
    33         {
    34             Console.WriteLine("Test Func");
    35         }
    36     }
    37 
    38     public class App
    39     {
    40         public App()
    41         {
    42             Test test = new Test();
    43 
    44             test.foo1();
    45 
    46             test.foo2();//这个会报错
    47         }
    48     }
    49 }

    注册的限制

    委托可以使用“=”、“+=”、“-=”三种符号来表示赋值,添加和移除一个函数,而事件修饰过的委托在自己的类中也可以使用这三个符号(注意子类也属于外部的类),而在外部的类中时则只能使用“+=”和“-=”来添加移除函数,不能使用“=”进行赋值,下面我们来看一个具体的例子:

     1 using System;
     2 
     3 namespace Study
     4 {
     5     class Program
     6     {
     7         static void Main(string[] args)
     8         {
     9             new App();
    10 
    11             Console.Read();
    12         }
    13     }
    14 
    15     public delegate void Foo();
    16 
    17     public class Test
    18     {
    19         public Foo foo1;
    20 
    21         public event Foo foo2;
    22 
    23         public Test()
    24         {
    25             foo1 = Func;
    26             foo1 += Func;
    27             foo1();
    28 
    29             foo2 = Func;
    30             foo2 += Func;
    31             foo2();
    32         }
    33 
    34         public void Func()
    35         {
    36             Console.WriteLine("Test Func");
    37         }
    38     }
    39 
    40     public class App
    41     {
    42         public App()
    43         {
    44             Test test = new Test();
    45 
    46             test.foo1 = Func;
    47             test.foo1 += Func;
    48             test.foo1();
    49 
    50             test.foo2 = Func;//这个会报错
    51             test.foo2 += Func;
    52             test.foo2();//这个会报错
    53         }
    54 
    55         public void Func()
    56         {
    57             Console.WriteLine("App Func");
    58         }
    59     }
    60 }
  • 相关阅读:
    Delphi TcxComboBox控件说明
    Delphi ComboBox的属性和事件、及几个鼠标事件的触发
    Delphi XE5的新功能“ TListView内置搜索过滤”
    可能是全网最全的解决摄像头无法创建视频捕捉过滤器问题?
    Delphi – TDataSet确定它是否在插入/编辑状态时被修改
    Delphi 获取DataSet传入参数后的SQL命令
    TClientDataSet[7]: 辨析 Field、FieldDef、Fields、FieldDefs、FieldList、FieldDefList
    枚举HasFlag函数实现的内部逻辑是什么
    在DBGrid中用代码实现按回车键跳到下一格的方法
    eclipse下没有Dynamic Web Project的处理方法
  • 原文地址:https://www.cnblogs.com/hammerc/p/4758157.html
Copyright © 2011-2022 走看看