事件与委托的问题???

我觉得事件就是委托
只不过是有2个参数(object 和 eventargs)和void返回类型和 关键字event的 特殊的委托

例如下面这两个程序,一个是用委托做的,一个是用事件做的。他们完成同一个功能。而且代码几乎相同
我就不懂了 , 既然能使用委托来完成,干吗还要用事件来完成,他们有什么区别,是什么关系呢??????????



///////////////////////////////////////委托//////////////////////////////////////////////
using System;

namespace  a
{
class UserInputMonitor
{
  public delegate void UserRequest();
  public  UserInputMonitor.UserRequest  OnUserRequest;
  public void Run()
  {    do  
   {   
    if (Console.ReadLine()=="h")  
    {    
     OnUserRequest();  
    }    
   }while(true);
   }
}
public class Client
{
     public static void Main()
       {  
      UserInputMonitor monitor=new UserInputMonitor();
      new Client(monitor);
      monitor.Run();
       }
private static void ShowMessage()
  {
   Console.WriteLine("委托"+"   "+"HaHa!!");
  }
Client(UserInputMonitor m)   {
     m.OnUserRequest = new UserInputMonitor.UserRequest(Client.ShowMessage);
     }
}
}
//////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////事件///////////////////////////////////////////////////

using System;

namespace 事件
{
using System;
class UserInputMonitor
{
  public delegate void UserRequest(object sender,EventArgs e); //定义委托
  public event UserRequest OnUserRequest; //此委托类型类型的事件
  public void Run()
  {
       
   do
   {  
    if (Console.ReadLine()=="h")
    {   

     Console.WriteLine("this is envent");
     OnUserRequest(this,new EventArgs());
    }   
   }while(true);
  }
}
    
public class Client
{
       
  public static void Main()
       
  {
    UserInputMonitor monitor=new UserInputMonitor();
       
   new Client(monitor);  
       
   monitor.Run();
       
  }
       
  private void ShowMessage(object sender,EventArgs e)
  {
       
   Console.WriteLine("事件"+"  "+"HaHa!!");
      
  }
Client(UserInputMonitor m)
    {
       m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);  
     }
}
 

 

答:

事件可以加好几个委托。其实事件是一个委托的链表(读过数据结构你就明白了),每一个+=就是把一个新的委托添加到事件里。触发事件就是触发事件底下n个委托。
另外,委托的签名可以是任何合法的函数签名,不一定要一个object一个EventArgs

委托实际上是一个函数指针,但它是由.Net管理的,所以是属于安全性的。

事件事实上是一个特殊的委托。

<think> 我们被要求回答C#中委托事件的区别。结合之前的对话历史,用户已经了解了委托的原理,现在转向事件委托的对比。 以下是回答要点: 1. 事件本质上是委托的封装器(事件基于委托) 2. 事件提供访问控制(事件只能在声明它们的类中触发,而委托可以在任何地方触发) 3. 事件提供更安全的订阅机制(只能通过+=和-=操作符添加或移除处理程序) 4. 设计意图不同:委托用于回调,事件用于对象状态变化通知(观察者模式) 5. 事件在接口中声明,而委托类型可以在其他地方定义 注意:引用之前提供的参考资料[^1]和[^2](用户给出的引用),但我们的回答要基于对C#的准确理解。 结构化回答: 1. 核心区别概述(委托是类型,事件是成员) 2. 访问控制差异(事件的外部调用限制) 3. 订阅机制对比(事件只能添加/移除,委托可直接赋值) 4. 设计目的差异 5. 实际应用场景对比 使用表格进行清晰对比(使用Markdown格式) 最后生成相关问题。 </think> ### C#委托事件的本质区别详解 委托事件是C#的核心机制,两者紧密相关但本质不同。以下是关键区别分析: #### 1. **核心概念差异** | **特性** | **委托** | **事件** | |----------------|---------------------------------------------|---------------------------------------------| | **本质** | 类类型(`System.Delegate`派生类) | 特殊成员(本质是委托的封装器) | | **声明方式** | `delegate void Handler(string msg);` | `public event Handler OnNotify;` | | **内存结构** | 存储方法指针+目标对象 | 包含私有委托字段+访问器方法 | | **设计目标** | 实现方法回调机制 | 实现安全的发布-订阅模型 | ```csharp // 委托声明(类型定义) public delegate void LogHandler(string message); // 事件声明(类成员) public class Logger { public event LogHandler OnLog; // 事件封装委托 } ``` #### 2. **访问控制差异(关键区别)** - **委托**: - 公共委托可被外部直接调用:`logger.OnLog?.Invoke("Test");` - 外部可完全覆盖委托链:`logger.OnLog = null;` - **事件**: - 外部只能通过`+=`/`-=`操作订阅:`logger.OnLog += HandleLog;` - **无法直接调用或覆盖**:编译器会阻止`logger.OnLog("Test")`操作 - 触发权仅限声明类内部:`OnLog?.Invoke("Internal call");` > 数学表达封装关系: > $$ \text{事件} = \text{私有委托} + \begin{cases} \text{add\_accessor} \\ \text{remove\_accessor} \end{cases} $$ #### 3. **设计目的差异 | **场景** | **委托典型应用** | **事件典型应用** | |------------------------|--------------------------------------|--------------------------------------| | 回调机制 | ✅ 线程池回调、LINQ查询 | ❌ 不适用 | | 组件间通信 | ❌ 风险高(易被覆盖) | ✅ 窗体控件事件(Button.Click) | | 多播广播 | ✅ 支持但风险高 | ✅ 安全实现(Observer模式) | | 接口定义 | ❌ 接口不能包含字段 | ✅ 可在接口声明事件 | #### 4. **编译后实现对比 ```csharp // 事件编译后实际代码 private LogHandler _onLog; // 私有委托字段 public event LogHandler OnLog { [MethodImpl(MethodImplOptions.Synchronized)] add { _onLog += value; } // 线程安全添加 remove { _onLog -= value; } // 线程安全移除 } ``` - 事件本质是**语法糖**,编译器生成: - 私有委托字段 - 两个访问器方法(add/remove) - 可选线程同步逻辑 #### 5. **典型应用场景 - **委托适用场景**: ```csharp // 异步回调 ThreadPool.QueueUserWorkItem(state => { // 耗时操作 callback?.Invoke(result); // 委托回调 }); ``` - **事件适用场景**: ```csharp // 观察者模式 public class Sensor { public event EventHandler<DataEventArgs> DataChanged; private void CheckData() { DataChanged?.Invoke(this, new DataEventArgs(data)); // 内部触发 } } ``` > 核心结论:**事件是封装了线程安全访问控制的委托字段**,通过限制外部访问实现安全的发布-订阅模型[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值