C#绘图程序不同子类独立维护shapes列表,EraserTool访问为空如何解决
问题根源
当前shapes是StartAndEndTool的实例字段,每创建一个StartAndEndTool子类(矩形工具/椭圆工具/橡皮擦工具)的实例,都会单独初始化一份属于该实例的shapes列表,不同工具实例的列表完全独立,因此橡皮擦实例读取的是自身的空列表,和其他工具添加的图形不属于同一份数据。
解决方案
有两种常用的实现方案,可根据业务场景选择:
方案1:将shapes改为静态成员
修改成本最低,适合单画布场景。静态成员属于类本身而非实例,所有子类实例共享同一份列表:
public abstract class StartAndEndTool : IPaint { // 加static修饰符,所有子类共享同一份列表 public static List<IPaint> shapes = new List<IPaint>(); // 其余原有abstract/virtual方法保留不变 }
注意:该方案不支持多画布/多文档场景,会出现不同画布的图形数据混杂的问题,这类场景建议使用方案2。
方案2:依赖注入统一图形列表
扩展性更强,耦合度更低,支持多画布场景。将图形列表从工具类内部抽离,所有工具操作的都是外部传入的同一份列表:
- 修改父类构造,接收外部传入的列表
public abstract class StartAndEndTool : IPaint { protected readonly List<IPaint> _shapes; // 构造函数要求传入统一的图形列表 public StartAndEndTool(List<IPaint> shapes) { _shapes = shapes; } // 其余原有abstract/virtual方法保留不变,例如: public abstract void Complete(); }
- 子类适配构造逻辑
public class RectangleTool : StartAndEndTool { public RectangleTool(List<IPaint> shapes) : base(shapes) {} public override void Complete() { // 操作的是统一的公共列表 _shapes.Add(new RectangleTool(_shapes)); } } public class EllipseTool : StartAndEndTool { public EllipseTool(List<IPaint> shapes) : base(shapes) {} public override void Complete() { _shapes.Add(new EllipseTool(_shapes)); } } public class EraserTool: StartAndEndTool { public EraserTool(List<IPaint> shapes) : base(shapes) {} public void Erase(IPaint target) { // 直接从公共列表删除目标图形即可 _shapes.Remove(target); } }
- 业务侧初始化时统一传入列表
在画布/主程序逻辑中初始化唯一的图形列表,所有工具实例都传入该列表:
// 单画布范围内初始化唯一的图形列表 var globalShapes = new List<IPaint>(); // 所有工具都传入同一份列表,保证数据统一 var rectTool = new RectangleTool(globalShapes); var ellipseTool = new EllipseTool(globalShapes); var eraserTool = new EraserTool(globalShapes);
内容的提问来源于stack exchange,提问作者Jiemie
相关产品推荐
相关产品推荐

