从存储命名坐标的DataTable构建2D多边形列表时点位追加异常的问题排查
问题成因排查
出现「分区名称可正常读取、但点位列表始终为空」的现象,通常是以下几类代码逻辑错误导致,按出现概率从高到低排序:
- PolyZone类的点位追加逻辑失效(占比最高)
- 类内部的点位列表未正确初始化,为null状态,调用Add方法时的空引用异常被上层全局捕获逻辑静默吞掉,导致后续循环中断,没有完成点位写入;
- Add方法内部每次调用都重新实例化点位列表,所有之前追加的点位会被直接覆盖丢弃;
- Add方法漏写核心写入语句,比如只对传入的point对象做属性赋值,没有执行
_pointList.Add(point)操作,根本没有把点位存入类的内部集合。
- 分组遍历的作用域错位
- 先创建PolyZone实例并加入总集合后,把逐行读取坐标、调用Add的代码块错放到分组循环的外层,导致每个PolyZone实例创建后没有执行过任何点位追加操作;
- 读取分组内坐标时,把生成的Point3D对象传给了临时创建的PolyZone变量,而非已经加入总集合的实例,导致总集合中存储的Zone始终是空壳。
- 坐标读取的静默中断
- 读取X/Y列值时未处理DBNull情况,当遇到空值行触发类型转换异常,被全局异常捕获拦截,导致循环读到空值行时直接中断,后续点位追加全部未执行;
- 把坐标生成、Add的逻辑写在GroupBy的投影委托中,但没有对分组结果进行枚举触发,只拿到了分组的key值,委托内的逻辑根本没有实际运行。
正确参考实现
可以对照下面的实现逻辑核对自己的代码:
// 1. 标准PolyZone类实现 public class PolyZone { public string ZoneName { get; set; } // 点位列表仅初始化一次,全程复用 private readonly List<Point3D> _pointList = new List<Point3D>(); // 对外暴露只读接口,避免外部意外修改列表 public IReadOnlyList<Point3D> Points => _pointList; public Point3D Center { get; set; } // 正确的点位追加方法 public void Add(Point3D point) { _pointList.Add(point); } } // 2. 修正后的BuildZoneList实现 public List<PolyZone> BuildZoneList() { var zoneList = new List<PolyZone>(); // 按分区名分组,提前过滤分区名为空的脏数据 var zoneGroups = zct.AsEnumerable() .Where(row => !string.IsNullOrWhiteSpace(row["Zone Name"].ToString())) .GroupBy(row => row["Zone Name"].ToString().Trim()); foreach (var group in zoneGroups) { // 每个分组创建独立的PolyZone实例 var currentZone = new PolyZone { ZoneName = group.Key }; // 遍历当前分组的所有行逐行取点 foreach (DataRow row in group) { // 做空值判断,避免DBNull转换异常 if (row["X_Coordinate"] == DBNull.Value || row["Y_Coordinate"] == DBNull.Value) { continue; } double x = Convert.ToDouble(row["X_Coordinate"]); double y = Convert.ToDouble(row["Y_Coordinate"]); // 搭配固定高程生成Point3D对象 var point = new Point3D(x, y, FixedElevationValue); currentZone.Add(point); } // 把填充完点位的Zone加入总集合 zoneList.Add(currentZone); } return zoneList; }
快速定位技巧
- 在PolyZone的Add方法内部加断点,运行时确认两个关键点:断点是否被正常触发、写入的内部列表是否正常累加值;
- 在遍历分组内DataRow的代码块加断点,确认循环是否按预期遍历完所有行,没有提前中断;
- 排除无效排查方向:DataGridView的列排序设置、数据绑定状态不会影响DataTable的
AsEnumerable()枚举结果,不需要在这部分浪费排查时间。
内容的提问来源于stack exchange,提问作者Gary Z。
相关产品推荐
相关产品推荐

