C#中为作为参数传递的Action添加和移除方法问题
问题根源
C#里委托是引用类型,但默认参数传递是按值传递——也就是说你把testAction传给AddModifier的removeModEvent参数时,传递的是原委托的副本。你在方法里给removeModEvent添加新的委托方法,只会修改这个副本,外部的testAction完全没变化,所以调用testAction?.Invoke()只会执行初始的方法。
解决方案
方法1:用ref关键字传递委托参数
把方法的参数改成ref Action removeModEvent,这样传递的是原委托变量的引用,方法内的修改会直接作用到外部的testAction上:
修改后的调用代码
Action testAction = () => { Console.WriteLine("initial call"); }; // 调用时加ref关键字 damage.AddModifier(type, value, ref testAction); testAction?.Invoke(); // 现在会输出"initial call"和"remove modifier"
修改后的方法定义
public void AddModifier(ModType type, float value, ref Action removeModEvent) { AddModifier(type, value); Action e = null; e = () => { Console.WriteLine("remove modifier"); RemoveModifier(type, value); removeModEvent -= e; }; removeModEvent += e; }
方法2:用包装类持有委托(适合复杂场景)
如果不想用ref,可以定义一个简单的包装类来持有Action,因为类是引用类型,传递的是引用,修改内部的Action会同步到外部:
// 定义包装类 public class ActionWrapper { public Action Action { get; set; } } // 调用方 var wrapper = new ActionWrapper { Action = () => { Console.WriteLine("initial call"); } }; damage.AddModifier(type, value, wrapper); wrapper.Action?.Invoke(); // 修改后的方法定义 public void AddModifier(ModType type, float value, ActionWrapper wrapper) { AddModifier(type, value); Action e = null; e = () => { Console.WriteLine("remove modifier"); RemoveModifier(type, value); wrapper.Action -= e; }; wrapper.Action += e; }
额外验证
调用testAction(或wrapper.Action)之后,再调用一次,只会输出"initial call"——因为lambda执行时已经把自己从委托链里移除了,符合你的需求。
内容的提问来源于stack exchange,提问作者CDreyer
相关产品推荐
相关产品推荐

