C#中委托关联订阅方法后无法通过实例调用Click事件的问题咨询
C#委托事件示例问题排查与修正
存在的问题
- 程序入口
Main方法不符合规范:C#控制台应用的入口点必须为static静态方法,原代码定义为实例方法,程序无法正常启动。 - 事件触发规则不符:C#中
event关键字修饰的成员仅允许在声明它的类内部直接调用触发,外部类仅能执行订阅+=、取消订阅-=操作,无法直接通过myButtonObj.Click("foo")的方式在类外触发事件。 - 缺少空值校验:直接调用委托前如果没有任何方法订阅,会触发空引用异常。
- 缺少触发逻辑:原代码仅完成了事件订阅,没有执行触发动作,订阅的方法自然不会运行。
修正方案
标准的事件使用规范是由事件所属类提供触发方法,外部通过调用该方法间接触发事件,修正后的完整代码如下:
using System; namespace DelegateConsoleExample { public delegate void MyEventHandler(string foo); class Program { // 修正1:将Main改为静态入口方法 static void Main(string[] args) { MyButton myButtonObj = new MyButton(); myButtonObj.Click += new MyEventHandler(OnSomethingHappened_1); myButtonObj.Click += new MyEventHandler(OnSomethingHappened_2); // 修正4:调用类提供的触发方法执行事件 myButtonObj.TriggerClick("foo"); } public static void OnSomethingHappened_1(string bar) { Console.WriteLine("x method runs"); Console.ReadKey(); } public static void OnSomethingHappened_2(string bar) { Console.WriteLine("y method runs"); Console.ReadKey(); } } public class MyButton { MyEventHandler myField; public event MyEventHandler Click { add { myField += value; } remove { myField -= value; } } // 修正2:新增类内部的事件触发方法 public void TriggerClick(string input) { // 修正3:空值校验,避免空引用异常 myField?.Invoke(input); } } }
补充说明
如果不需要事件的封装特性,仅需要可外部调用的多播委托,可以将MyButton类中的Click修改为公共委托字段,去掉event关键字和自定义的add/remove访问器,即可直接在外部调用myButtonObj.Click("foo"),但这种方式不符合事件的设计原则,不推荐在常规场景使用。
内容的提问来源于stack exchange,提问作者GNZ
相关产品推荐
相关产品推荐

