将事件作为Action参数传递时遇访问限制错误的解决求助
解决事件作为参数传递的报错问题
这个报错的核心原因很明确:C#里的事件在类外部只能通过+=或-=来订阅/取消订阅,不能直接把事件本身当作委托类型的参数传递。你尝试把locationManager.OnPositionUpdated(一个事件)传给需要Action<GPSReading>的构造函数参数,这就违反了事件的封装规则,所以编译器会报错。
下面给你两种可行的解决思路:
方案1:直接传入LocationManager实例,在构造函数内订阅事件
修改AccelCalculator的构造函数,让它接收LocationManager实例,而不是单独的事件参数,然后在构造函数内部直接订阅事件:
public AccelCalculator(SensorManager sensorManager, Action<double, double> OnNewData, LocationManager locationManager) { this.sensorManager = sensorManager; sensorManager.OnNewAccelReading += CalibrateAccel; // 直接在构造函数里订阅LocationManager的事件 locationManager.OnPositionUpdated += ProcessGPS; OnNewDataCalculation += OnNewData; }
调用的时候就改成这样:
accelCalculator = new AccelCalculator(sensorManager, RecordAccel, locationManager);
这种方式最直接,也符合依赖注入的思路,让AccelCalculator明确依赖它需要的LocationManager。
方案2:在调用处封装订阅逻辑(如果不想传递整个LocationManager)
如果你不想把整个LocationManager传给AccelCalculator,可以在构造函数外先完成事件订阅,或者给AccelCalculator添加一个专门的订阅方法:
首先修改AccelCalculator,去掉事件参数,添加一个订阅GPS的方法:
public AccelCalculator(SensorManager sensorManager, Action<double, double> OnNewData) { this.sensorManager = sensorManager; sensorManager.OnNewAccelReading += CalibrateAccel; OnNewDataCalculation += OnNewData; } // 添加专门的方法来订阅GPS事件 public void SubscribeToGPS(Action<GPSReading> gpsEvent) { gpsEvent += ProcessGPS; }
然后在调用的时候,直接用+=来订阅:
accelCalculator = new AccelCalculator(sensorManager, RecordAccel); locationManager.OnPositionUpdated += accelCalculator.ProcessGPS;
如果ProcessGPS是私有方法,那就用lambda包装:
accelCalculator = new AccelCalculator(sensorManager, RecordAccel); locationManager.OnPositionUpdated += reading => accelCalculator.ProcessGPS(reading);
为什么会报错?
再补充下原理:C#的事件是对委托的封装,它只对外暴露add和remove访问器,外部代码不能直接获取事件底层的委托实例,也不能把事件当作参数传递——这是为了防止外部代码意外覆盖事件的所有订阅者(比如直接用=赋值),保证事件的安全性和封装性。
内容的提问来源于stack exchange,提问作者Moffen
相关产品推荐
相关产品推荐

