C#中ArrayList内的结构体对象无法更新问题求助
C#中ArrayList存储结构体对象修改属性无效的问题解决
问题场景
使用ArrayList存储自定义line结构体对象时,修改取出对象的PointB属性后,ArrayList中存储的对象属性并未更新,导致渲染的线条没有变化。
原代码示例
缓存与渲染代码:
// Line Cache public ArrayList lineCache = new ArrayList(); public object drawLine(Point start, Point finish) { line lineObject = new line(start, finish); object lineBuffer = lineCache.Add(lineObject); return lineBuffer; } public void render() { while (!renderObject.IsDisposed) { renderTarget.BeginDraw(); renderTarget.Clear(transparencyDirect2D); // Line Updaters for (int i = 0; i < lineCache.Count; i++) { line cache = (line)lineCache[i]; renderTarget.DrawLine(drawingBrush, cache.PointA, cache.PointB); } renderTarget.EndDraw(); new System.Threading.ManualResetEvent(false).WaitOne(5); } }
创建并修改线条的代码:
line tracer = (line)canvas.drawLine(new Point(0,0), new Point(900, 900)); for (int i = 0; i < 200; i++) { tracer.PointB = new Point(100, 100 + i); }
问题原因
- 结构体是值类型:从
ArrayList中取出结构体时,会返回该结构体的副本,而非原始对象的引用。修改副本的属性只会影响副本,不会改变ArrayList中存储的原始结构体。 ArrayList.Add返回值错误使用:Add方法实际返回的是元素在集合中的索引(int类型),而非添加的对象。原代码中将其强制转换为line类型会抛出类型转换异常,实际运行中tracer并非ArrayList中的原始对象。
解决方案
方案1:将结构体改为类(推荐)
把line从值类型(struct)改为引用类型(class),这样操作的是对象引用,修改属性会直接影响ArrayList中的原始对象:
// 将line定义为class public class line { public Point PointA { get; set; } public Point PointB { get; set; } public line(Point start, Point finish) { PointA = start; PointB = finish; } } // 使用泛型List替代ArrayList,避免装箱拆箱,提升类型安全性 public List<line> lineCache = new List<line>(); // 修改drawLine方法,直接返回line对象 public line drawLine(Point start, Point finish) { line lineObject = new line(start, finish); lineCache.Add(lineObject); return lineObject; }
修改线条属性的代码无需额外改动,直接修改即可生效:
line tracer = canvas.drawLine(new Point(0,0), new Point(900, 900)); for (int i = 0; i < 200; i++) { tracer.PointB = new Point(100, 100 + i); }
方案2:保留结构体,修改后重新存入集合
如果必须使用结构体,需要将修改后的结构体重新放回ArrayList,覆盖原始元素:
// 修改drawLine方法,返回元素的索引 public int drawLine(Point start, Point finish) { line lineObject = new line(start, finish); int index = lineCache.Add(lineObject); return index; }
修改属性时,更新后重新存入集合:
int tracerIndex = canvas.drawLine(new Point(0,0), new Point(900, 900)); for (int i = 0; i < 200; i++) { line tracer = (line)canvas.lineCache[tracerIndex]; tracer.PointB = new Point(100, 100 + i); // 将修改后的结构体放回集合 canvas.lineCache[tracerIndex] = tracer; }
内容的提问来源于stack exchange,提问作者Require
相关产品推荐
相关产品推荐

