为何List<Point3DCollection>添加对象时new与Clear结果不同?
为什么
new Point3DCollection()和point.Clear()对全局列表_points的影响不同? 现有全局List<Point3DCollection>类型变量_points,编写代码时:创建Point3DCollection实例point并添加元素后,将其加入_points;随后执行point = new Point3DCollection()创建新实例并添加元素再加入_points,代码运行正常。但如果将point = new Point3DCollection()替换为point.Clear(),运行结果会出现异常。疑惑为何使用new重新赋值后,_points中第一个元素不受后续操作影响,而使用Clear则会影响,背后的原理如下:
问题代码
Point3DCollection point=new Point3DCollection(); ScreenSpaceLines3D line = new ScreenSpaceLines3D(); point.Add(new Point3D(SketchList[0].x0/2, SketchList[0].y0, SketchList[0].z0 + 1)); point.Add(new Point3D(SketchList[0].x1, SketchList[0].y1, SketchList[0].z0 + 1)); point.Add(new Point3D(SketchList[0].x1, SketchList[0].y1, SketchList[0].z0 + 1)); point.Add(new Point3D(SketchList[0].x0/2, SketchList[0].y1, SketchList[0].z0 + 1)); _points.Add(point); // 这里用new正常,换成Clear就出问题 point = new Point3DCollection(); //point.Clear(); point.Add(new Point3D(SketchList[0].x0, SketchList[0].y0, SketchList[0].z0 + 2)); point.Add(new Point3D(SketchList[0].x1, SketchList[0].y1, SketchList[0].z0 + 2)); point.Add(new Point3D(SketchList[0].x1, SketchList[0].y1, SketchList[0].z0 + 2)); point.Add(new Point3D(SketchList[0].x0, SketchList[0].y1, SketchList[0].z0 + 2)); _points.Add(point); line = new ScreenSpaceLines3D() { Points = _points[0], Thickness = 2, Color = Colors.Green }; View3D_Model.Children.Add(line); line = new ScreenSpaceLines3D() { Points = _points[1], Thickness = 2, Color = Colors.Gold }; View3D_Model.Children.Add(line);
注:_points是全局的List<Point3DCollection>类型变量
核心原理:引用类型的赋值逻辑
Point3DCollection是引用类型,这类类型的变量存储的不是实际数据,而是指向内存中对象实例的地址。
当执行
point = new Point3DCollection()时:- 在内存中创建一个全新的
Point3DCollection实例,分配新的内存地址。 - 将
point变量的指向从原来的实例地址,切换为这个新实例的地址。 - 此时
_points[0]存储的是旧实例的地址,和point现在指向的新实例完全无关,后续对point的操作只会影响新实例,不会改动_points[0]对应的旧实例。
- 在内存中创建一个全新的
当执行
point.Clear()时:point变量仍然指向之前加入_points的那个实例(内存地址未变)。Clear()方法直接清空该内存地址下Point3DCollection实例的所有元素。- 因为
_points[0]存储的也是这个实例的地址,所以_points[0]对应的实例也被清空。后续给point添加元素,其实是往同一个实例里添加,最终_points里的两个元素指向的是同一个实例,导致两条线共用同一组点数据,出现异常。
简单总结:new是创建了一个全新的对象,Clear是在原有对象上修改数据,而_points中存储的是对象的引用(地址),因此前者不会影响旧对象,后者会直接修改旧对象。
内容的提问来源于stack exchange,提问作者Adel Lotfi
相关产品推荐
相关产品推荐

