event与delegate的区别

首先,通过加入event关键字,在编译的时候编译器会自动针对事件生成一个私有的字段(与此事件相关的委托),以及两个访问器方法,即add访问器方法以及remove访问器方法,用于对事件的注册及注销(对事件使用+=及-=操作时就是调用的这两个方法)。
我想你们的问题主要是,实际上声明一个委托类型的字段也可以实现这些功能。
实际上之所以采用event而不直接采用委托,实际上还是为了封装。可以设想一下,如果直接采用公共的委托字段,类型外部就可以对此字段进行直接的操作了,比如将其直接赋值为null。
而使用event关键字就可以保证对事件的操作仅限于add访问器方法以及remove访问器方法(即只能使用+=及-=)

event与delegateC#中的两个关键字,在微软的例程中常见它们一起出现,那么他们之间有什么关系呢?

 

想看专业的解释就看: 
.NET Famework SDK文档-〉参考-〉编译器和语言参考-C#-C#语言规范-10.7.1类似字段的事件 
里面有详细的解释。 
这里我想就编译时发生的事情做一下描述。 

上面的参考中有一句:引发一个事件调用一个由该事件表示的委托完全等效。

什么意思呢?

我觉得可以这样表述:事件的引发是通过调用委托实现的,而委托不仅仅可以用来实现事件的引发。 
我写了下面一段测试代码,我们可以看看编译器到底对event做了些什么。 

 

我们用ildasm工具打开生成的IL代码: 
 
 

可以看到delegate abc实际上是从MulticastDelegate继承而来的一个类。

而在我们自己声明的thisevent事件、d()e()方法之外,多出了一个thisevent字段和两个方法add_thisevent()remove_thisevent()

正如上面提到的那篇参考内描述的那样,一个事件的声明是可以转化为一个代理字段的声明加上添加、删除两种方法的事件操作。 


我们查看thisevent事件的IL代码:

 

.event test4eventil.Class1/ abc thisevent 

  .addon instance void test4eventil.Class1::add_thisevent(class test4eventil.Class1/
abc) 
  .removeon instance void test4eventil.Class1::remove_thisevent(class test4eventil.Class1/
abc) 
}
 //  end of event Class1::thisevent 

可以看到,实际上add_thisevent()remove_thisevent()是包含在thisevent事件中的两个方法。 

那么,这两个方法与delegate有什么关系呢?

我们看看add_thisevent()IL代码: 

.method public hidebysig specialname instance void   
        add_thisevent(class test4eventil.Class1/abc 'value'
) cil managed synchronized 

  // 代码大小       24 (0x18)
 
  .maxstack  3
 
  IL_0000:  ldarg.0
 
  IL_0001:  ldarg.0
 
  IL_0002:  ldfld      class test4eventil.Class1/
abc test4eventil.Class1::thisevent 
  IL_0007:  ldarg.1
 
  IL_0008: call       class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class
 [mscorlib]System.Delegate)
  IL_000d:  castclass  test4eventil.Class1/
abc 
  IL_0012:  stfld      class test4eventil.Class1/
abc test4eventil.Class1::thisevent 
  IL_0017:  ret 
}
 //  end of method Class1::add_thisevent 

反编译后如下: 

public void add_thisevent(abc value) 
    this.thisevent = (abc) Delegate.Combine(this
.thisevent, value); 
}
 

remove_thisevent()则是:

 

public void remove_thisevent(abc value) 
    this.thisevent = (abc) Delegate.Remove(this
.thisevent, value); 
}
 


也就是说,实际上,添加一个事件的绑定,实际上就是向该事件表示的委托列表中添加一项委托。而取消一个事件的绑定,就是从委托列表中删除一项委托。 

所以,对event的绑定都是通过在delegate列表中添加、删除项来实现的。

另外,需要注意的一点是:除了在event对象声明的类内部,event对象只能用在+=-=的左边。

Comments
不错, 
效果一样, 
event通常只能被所申明的类访问.
  re: event与delegate的关系
Ninpute
你甚至可以自己写那个add和remove方法,以求最大控制
  re: event与delegate的关系  idior

    public class  Class1 
    

        public delegate void
 abc(); 
        public event
 abc thisevent; 
        public
 Class1() 
        

            thisevent += new
 abc(d); 
            thisevent += new
 abc(e); 
            thisevent -= new
 abc(d); 
            thisevent = thisevent - new
 abc(e); 
        }
 
 
        public void d(){}
 
        public void e(){}
 
    }
 


event与delegate的区别
 首先,通过加入event关键字,在编译的时候编译器会自动针对事件生成一个私有的字段(与此事件相关的委托),以及两个访问器方法,即add访问器方法以及remove访问器方法,用于对事件的注册及注销(对事件使用+=及-=操作时就是调用的这两个方法)。
我想你们的问题主要是,实际上声明一个委托类型的字段也可以实现这些功能。
实际上之所以采用event而不直接采用委托,实际上还是为了封装。可以设想一下,如果直接采用公共的委托字段,类型外部就可以对此字段进行直接的操作了,比如将其直接赋值为null。
而使用event关键字就可以保证对事件的操作仅限于add访问器方法以及remove访问器方法(即只能使用+=及-=)

event与delegateC#中的两个关键字,在微软的例程中常见它们一起出现,那么他们之间有什么关系呢?

 

想看专业的解释就看: 
.NET Famework SDK文档-〉参考-〉编译器和语言参考-C#-C#语言规范-10.7.1类似字段的事件 
里面有详细的解释。 
这里我想就编译时发生的事情做一下描述。 

上面的参考中有一句:引发一个事件调用一个由该事件表示的委托完全等效。

什么意思呢?

我觉得可以这样表述:事件的引发是通过调用委托实现的,而委托不仅仅可以用来实现事件的引发。 
我写了下面一段测试代码,我们可以看看编译器到底对event做了些什么。 

 

我们用ildasm工具打开生成的IL代码: 
 

可以看到delegate abc实际上是从MulticastDelegate继承而来的一个类。

而在我们自己声明的thisevent事件、d()e()方法之外,多出了一个thisevent字段和两个方法add_thisevent()remove_thisevent()

正如上面提到的那篇参考内描述的那样,一个事件的声明是可以转化为一个代理字段的声明加上添加、删除两种方法的事件操作。 


我们查看thisevent事件的IL代码:

 

.event test4eventil.Class1/ abc thisevent 

  .addon instance void test4eventil.Class1::add_thisevent(class test4eventil.Class1/
abc) 
  .removeon instance void test4eventil.Class1::remove_thisevent(class test4eventil.Class1/
abc) 
}
 //  end of event Class1::thisevent 

可以看到,实际上add_thisevent()remove_thisevent()是包含在thisevent事件中的两个方法。 

那么,这两个方法与delegate有什么关系呢?

我们看看add_thisevent()IL代码: 

.method public hidebysig specialname instance void   
        add_thisevent(class test4eventil.Class1/abc 'value'
) cil managed synchronized 

  // 代码大小       24 (0x18)
 
  .maxstack  3
 
  IL_0000:  ldarg.0
 
  IL_0001:  ldarg.0
 
  IL_0002:  ldfld      class test4eventil.Class1/
abc test4eventil.Class1::thisevent 
  IL_0007:  ldarg.1
 
  IL_0008: call       class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class
 [mscorlib]System.Delegate)
  IL_000d:  castclass  test4eventil.Class1/
abc 
  IL_0012:  stfld      class test4eventil.Class1/
abc test4eventil.Class1::thisevent 
  IL_0017:  ret 
}
 //  end of method Class1::add_thisevent 

反编译后如下: 

public void add_thisevent(abc value) 
    this.thisevent = (abc) Delegate.Combine(this
.thisevent, value); 
}
 

remove_thisevent()则是:

 

public void remove_thisevent(abc value) 
    this.thisevent = (abc) Delegate.Remove(this
.thisevent, value); 
}
 


也就是说,实际上,添加一个事件的绑定,实际上就是向该事件表示的委托列表中添加一项委托。而取消一个事件的绑定,就是从委托列表中删除一项委托。 

所以,对event的绑定都是通过在delegate列表中添加、删除项来实现的。

另外,需要注意的一点是:除了在event对象声明的类内部,event对象只能用在+=-=的左边。

Comments
不错, 
效果一样, 
event通常只能被所申明的类访问.
  re: event与delegate的关系
Ninpute
你甚至可以自己写那个add和remove方法,以求最大控制
  re: event与delegate的关系

    public class  Class1 
    

        public delegate void
 abc(); 
        public event
 abc thisevent; 
        public
 Class1() 
        

            thisevent += new
 abc(d); 
            thisevent += new
 abc(e); 
            thisevent -= new
 abc(d); 
            thisevent = thisevent - new
 abc(e); 
        }
 
 
        public void d(){}
 
        public void e(){}
 
    }
 
### C# 中 `event` 和 `delegate` 的关系及区别 #### 1. 基本概念 在 C# 中,`delegate` 是一种类型安全的函数指针,用于封装方法的引用。它可以指向静态方法或实例方法,并允许调用这些方法而不必知道它们的具体实现细节[^1]。 而 `event` 则是对 `delegate` 的进一步封装,主要用于发布-订阅模式下的事件处理机制。通过 `event` 关键字定义的成员可以被外部访问,但它仅限于添加 (`+=`) 或移除 (`-=`) 处理程序的操作,无法直接调用底层的 `delegate` 实例[^4]。 --- #### 2. 使用方式对比 ##### (1)Delegate 的基本使用 以下是 `delegate` 的典型定义和使用: ```csharp // 定义一个委托类型 public delegate void NotifyEventHandler(object sender, EventArgs e); class Program { static void Main() { // 创建委托实例并绑定方法 NotifyEventHandler handler = new NotifyEventHandler(MethodToInvoke); // 调用委托 handler(null, null); } static void MethodToInvoke(object sender, EventArgs e) { Console.WriteLine("Method invoked!"); } } ``` 上述代码展示了如何定义和使用 `delegate` 来封装方法调用逻辑[^2]。 ##### (2)Event 的基本使用 当我们将 `delegate` 封装到 `event` 中时,其主要目的是为了提供更严格的访问控制,防止外部代码直接触发事件。下面是一个简单的例子: ```csharp using System; public class Publisher { // 定义事件 public event Action OnSomethingHappened; public void DoWork() { Console.WriteLine("Doing work..."); OnSomethingHappened?.Invoke(); // 触发事件 } } public class Subscriber { public Subscriber(Publisher publisher) { // 订阅事件 publisher.OnSomethingHappened += HandleEvent; } private void HandleEvent() { Console.WriteLine("Event handled by subscriber."); } } class Program { static void Main() { var publisher = new Publisher(); var subscriber = new Subscriber(publisher); publisher.DoWork(); // 输出: Doing work... Event handled by subscriber. } } ``` 在这个示例中,`OnSomethingHappened` 是基于 `Action` 类型的一个事件。只有 `Publisher` 可以触发它,而其他类可以通过订阅来响应这个事件[^3]。 --- #### 3. 主要区别 | 特性 | Delegate | Event | |---------------------|---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------| | **本质** | 函数指针,表示一组可执行的方法集合 | 对 `delegate` 的封装,专门用于事件处理 | | **访问权限** | 公开可见,任何地方都可以调用 | 提供受限访问,只能由声明它的类内部触发 | | **适用场景** | 方法回调、多线程通信 | 发布-订阅模型 | | **操作限制** | 支持直接调用 | 不支持直接调用;仅能通过 `+=` 添加处理器或通过 `-=` 移除处理器 | --- #### 4. 使用场景分析 - 如果需要实现跨组件之间的解耦设计(比如 GUI 控件的通知机制),推荐优先考虑 `event`,因为它提供了更好的安全性。 - 当只需要简单地传递方法引用或者构建复杂的回调链表时,则可以直接使用 `delegate`。 --- ### 总结 虽然 `delegate` 和 `event` 都涉及到了方法的动态调用,但两者的设计目标不同:前者侧重灵活性,后者则强调语义上的清晰性和安全性。因此,在实际开发过程中应根据具体需求选择合适的工具。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值