C#对象数组,非常大,寻找更好的方法

好吧,所以在我的一个项目中,我试图重新制作存储某些变量的方式,我有一个简单的对象数组。 这些对象引用的类是:

class Blocks { public byte type = Block.Empty; byte lastblock = Block.Zero; } 

我计划向它添加更多内容,在当前类类型中是对象当前值,而lastblock是对象的用途。

我像这样创建数组:

 blocks = new Blocks[width * depth * length]; for (int i = 0; i < ((width * length) * depth); i++) { blocks[i] = new Blocks(); } 

我遇到的问题是,当我创建一个非常大的数组(对于那些不喜欢数学的人来说,512,512,512或134217728)时,数组变得非常大,超过3.5演出。

创建这个数组的旧方法有点简单,但扩展起来要困难得多,它简单地创建了一个表示当前块的字节数组,并且在实际加载时似乎只使用了2兆的ram(我从此没有得到) 134217728字节应该在134兆左右……对吧?)。 令我感到困惑的是,对象引用可以产生更多的ram使用。

我做错了什么,或者我应该回到原来的做法? 我想对象引用只是因为它意味着我的所有变量都在1个数组中,而不是在4个独立的数组中,这似乎对系统来说更好。

编辑:

经过几种不同的方式,我发现了变化

 class Blocks 

 struct Blocks 

做了一个与众不同的世界,感谢社区提供未来使用的欢迎提示,遗憾的是我不想在结构中添加两个字节并将其调用完成,这就是我停下来测试我的设计并结束了原始问题。 在结构中添加任何其他内容(至少在我的列表中的任何其他内容,意味着播放器对象引用或播放器名称字符串。)它会导致内存不足exception,这意味着我将无法毕竟使用这个系统。

但是如何做到这一点的知识将来会非常有用。 为此,再次感谢你。

这是我尝试使用结构类型而不是类类型

 public struct Block { public byte _current; public byte _last; } public static void RunSnippet() { Block[] blocks = new Block[512 * 512 * 512]; for (int i = 0; i < ((512 * 512) * 512); i++) { blocks[i] = new Block(); } } 

该片段几乎立即运行并占用了大约267 Mb的RAM。

如果可能,请尝试使用struct

您可以使用List类来管理无限数量的对象。 请看一下我提供的链接。 您可以在列表中添加无限(理论上)数量的对象。

使用列表,您可以轻松地按索引访问任何项目。 它还具有搜索,排序和操作其中包含的对象的方法。

如果你使用list,你的代码看起来有点像下面 –

 List blocks = new List(); for (int i = 0; i < ((width * length) * depth); i++) // The amount of items that you want to add { Blocks b = new Blocks(); blocks.Add(b); } 

您可以访问此列表中的每个项目,如下所示 -

 foreach(Blocks b in blocks) { // You have the object, do whatever you want } 

您可以找到列表中包含的对象的任何特定索引。 请参阅此方法示例 。

因此,使用列表,您将能够以统一的方式轻松管理大量对象。

要了解更多信息,请转到此处 。

您应该考虑使用“struct”而不是“class”。

http://msdn.microsoft.com/en-us/library/ah19swz4(v=vs.71).aspx

“结构类型适用于表示轻量级对象,如Point,Rectangle和Color。尽管可以将点表示为类,但在某些情况下结构更有效。例如,如果声明数组为1000点对象,你将为引用每个对象分配额外的内存。在这种情况下,结构更便宜。“

如果您尝试,请发布您的结果。

创建arrays时,还可以在每个单元格上实例化块。 你真的需要那样做吗?

blocks[i] = new Blocks() ;

如果不实例化Blocks,则只需要一个空引用数组。 在访问代码中,您可以检查null并返回默认值。 这些方面的东西:

 if(blocks[i,j] == null) return new Blocks(); else return blocks[i,j]; 

写入时还要检查是否有,如果没有,请先创建它。 这应该可以节省大量内存。

使用锯齿状数组或嵌套列表也应该有很多帮助。

关心GJ

结构是前进的方向,并且将开启使用不安全的代码/指针算法进行优化的可能性

 struct Block { byte Current; byte Last; } Block[] blocks = new Block[512 * 512 * 512]; unsafe { Block* currentBlock = &blocks; for (int i = 0; i < (512 * 512) * 512; i++) { currentBlock->Current = 0xff; currentBlock->Last = 0x00; currentBlock++; } } 

当然有人会来,说可变的结构是邪恶的! (只有你不知道如何使用它们)

阅读: 对象开销:隐藏的.NET内存分配成本 。

您的对象的总成本类似于16个字节(在32位系统上)。 (8个字节用于“标题”,4个字节用于您的字段,4个用于参考)和512 * 512 * 512 * 16 = 2.1gb 🙂

但你可能是64位系统,所以它是16 + 8 + 8 = 28,所以4.29gb