很久以前我写了一个对象池系统(嗯,大部分是我当时需要的部分)。现在程序已经在它上面进化了,我发现了一个我认为我在实现池时没有的缺陷。
本质上,池将一个对象作为构造函数,并使用反射克隆它以创建该对象的数组。这是在池中创建对象的函数的实现:
poolSize i = 0;
T[] oldData = null;
if (this.chunks != null && this.chunks.Length > 0)
{
oldData = new T[this.depth];
Array.Copy(this.chunks, oldData, this.chunks.Length);
}
this.chunks = new T[this.depth + this.depthIncrement];
if (oldData != null)
{
Array.Copy(oldData, this.chunks, oldData.Length);
}
for (i = this.depth; i < this.depth + this.depthIncrement; i++)
{
this.chunks[i] = Cloner.CloneObjectWithIL(this._template);
this.freeQueue.Add(i);
}
this.depth += this.depthIncrement;
现在,检查 Object.ReferenceEquals(pool.chunks[0], pool.chunks[1]) 返回 false - 所以看起来数组的每个索引都是它自己的对象,而不仅仅是对一个对象的一堆引用。
现在在主代码中,我们使用 GetObject 方法从池中获取一个对象:
public T GetObject(T tmp)
{
T retObj = tmp;
this.chunks[this.volume] = retObj;
this.usedQueue.Add(this.volume);
this.volume++;
return retObj;
}
我遇到了一些受保护的内存错误(C# 相当于 SEGFAULT?)所以我继续进行一些调试。所以我使用了我通常不会做的代码,因为它违背了池背后的一些目的:
Map.Entity tmp = Map.Entity.EntityPool.chunks[0];
tmp.SetPosition(m, 1, 9);
现在,当我在那之后添加一个断点并查看块数组时,块数组的每个元素的位置都是 (1, 9),而除了索引 0 之外,它们都应该是 (0, 0)。
我在这里想念什么?