如何在C#运行时创建无关联方法的空EventHandler?
问题背景
我想要创建一个未附加任何方法的EventHandler,并且希望在运行时而非编译时完成初始化,后续可以动态添加方法并触发事件。我尝试了以下代码,但第一行就出现编译错误:
EventHandler eventHandler = new EventHandler(); // 编译错误 if(some_condition) { eventHandler += (sender, e) => { Console.WriteLine("some condition is true"); }; } else { eventHandler += (sender, e) => { Console.WriteLine("some condition is false"); }; } eventHandler?.Invoke(this, EventArgs.Empty);
错误原因是无法无参创建EventHandler实例;虽然用空lambda表达式EventHandler eventHandler = new EventHandler((sender, e) => { });可以编译,但写法不够简洁,请问该如何正确初始化EventHandler?
回答
这是个很典型的委托初始化场景,有两种简洁的方案可以满足你的需求:
方案1:直接初始化为null(最推荐、最简洁)
委托属于引用类型,默认值就是null,直接把它初始化为null完全可行。后续使用+=添加委托逻辑时,.NET会自动处理空委托的组合,不会出现异常:
EventHandler eventHandler = null; if (some_condition) { eventHandler += (sender, e) => Console.WriteLine("some condition is true"); } else { eventHandler += (sender, e) => Console.WriteLine("some condition is false"); } // 用null条件运算符确保调用安全,避免空引用异常 eventHandler?.Invoke(this, EventArgs.Empty);
这种写法完全符合你的需求:初始状态下没有绑定任何方法,运行时根据条件动态添加后再触发事件,代码也足够简洁。
方案2:使用EventHandler.Empty(无需null判断)
如果你希望初始的委托实例始终“有效”(即使没有绑定任何方法),可以使用.NET提供的EventHandler.Empty字段——它是一个预先定义好的空委托实例,调用它不会执行任何逻辑,也不会抛出空引用异常:
EventHandler eventHandler = EventHandler.Empty; if (some_condition) { eventHandler += (sender, e) => Console.WriteLine("some condition is true"); } else { eventHandler += (sender, e) => Console.WriteLine("some condition is false"); } // 无需额外判断,直接调用即可 eventHandler.Invoke(this, EventArgs.Empty);
这个方案适合你不想处理null情况的场景,初始状态下的委托是合法的,调用时不用加?.。
补充说明:为什么new EventHandler()会报错?
EventHandler是委托类型,它的设计目的是封装方法引用,因此它的构造函数必须接收一个与委托签名匹配的方法(或lambda表达式)作为参数——无参构造没有实际意义,所以.NET并没有提供无参的EventHandler构造函数,这就是你遇到编译错误的核心原因。
内容的提问来源于stack exchange,提问作者Janos Nagy

