Skip to content

委托和事件 #43

@Henrik-Xu

Description

@Henrik-Xu

委托和事件

委托

C# 中通过 delegate 关键字,声明委托。

委托的基本概念:委托其实就是一个方法的原型:返回值 + 参数类型和个数

委托:方法的指针(方法的代表)

委托创建的基本步骤 :

  1. 声明委托
public delegate double ShowRateDelegate(int attendCount, int studentCount);
  1. 根据委托定义具体的方法
public class StudentStat
{
    //【2】编写具体方法
    public int StatAdvancedClass(int count1, int count2)
    {
        return (double)count1 / (double)count2;
    }
    public int StatCommonClass(int count1, int count2)
    {
        return (double)count1 / (double)count2;
    }
}

// 提供委托注册的方法
static ShowRateDelegate CallDelegate()
{
    return new StudentStat().StatAdvancedClass;
}
  1. 创建委托对象(关联具体的方法)
static void Main(string[] args)
{
    StudentStat stat = new StudentStat();
    ShowRateDelegate rateDelegate = null;

     rateDelegate += CallDelegate();
    Console.Read();
}
  1. 通过委托调用方法,而不是直接使用方法
double result = rateDelegate.Invoke(100,200);

事件

C# 中通过 event 关键字,声明事件,事件是委托的语法糖,使得委托更加安全。

  1. 问题:如果我们没有把委托成员变量定义为私有的,调用者就可以直接访问委托列表。这样,调用者就可以把变量重新赋值为新的委托对象。

这样就删除了当前要调用的方法列表,更糟糕的是,调用者可以直接调用委托的调用列表。

  1. 结论:公共的委托成员打破了封装,不仅会导致代码难以维护和调式,还是导致应用程序的安全风险。

  2. event: 为了简化自定义方法的构建来为委托调用列表增加和删除方法的问题。event编译时会提供注册和注销方法以及任何必须要的委托

类型成员变量。而且这些委托成员变量总是声明为私有的,这样我们不能直接从触发事件的对象访问他们。所以说 event 关键字就是一个语

法糖。

  1. 定义事件:
  • 声明委托
public delegate double ShowRateDelegate(int attendCount, int studentCount);
  • 使用 event 关键字声明委托变量
event ShowRateDelegate rateDelegate = null;
  1. 源码观察 event 本质

C# 事件实际会扩展为两个隐藏的公共方法,一个带 add_ 前缀, 一个带 remove_ 前缀,前缀后面是事件的名称。

内部对 Delegate.Combine()Delegate.Remove() 的调用。

.method private hidebysig specialname static 
        void  add_rateDelegate(class DelegateTest.ShowRateDelegate 'value') cil managed
{
  lass [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
                                                                                          class [mscorlib]System.Delegate)

}

.method private hidebysig specialname static 
        void  remove_rateDelegate(class DelegateTest.ShowRateDelegate 'value') cil managed
{
   class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
                                                                                         class [mscorlib]System.Delegate)

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions