You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

问题原因

  1. 结构体是值类型:从ArrayList中取出结构体时,会返回该结构体的副本,而非原始对象的引用。修改副本的属性只会影响副本,不会改变ArrayList中存储的原始结构体。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 21:06:24