我的意思是它真的可能吗? MSDN表示数组是固定大小的,调整大小的唯一方法是#34; copy-to-new-place"。但也许有可能使用内部CLR结构的不安全/一些魔法,它们都是用C ++编写的,我们有一个完整的内存控制,可以调用realloc
等等。
我没有为此问题提供代码,因为我甚至不知道它是否可以存在。
我不是在谈论Array.Resize方法等等,因为他们显然没有必要的行为。
假设我们有一个带有2GB ram的标准x86进程,并且我有1.9GB由单个数组填充。然后我想释放一半。所以我想写一些类似的东西:
MagicClass.ResizeArray(ref arr, n)
并且不要获得OutOfMemoryException。 Array.Resize将尝试分配另一千兆字节的RAM,并将失败,1.9 + 1> 2GB OutOfMemory。
答案 0 :(得分:2)
您可以尝试Array.Resize()
:
int[] myArray = new int[] { 1, 2, 3, 4 };
int myNewSize = 1;
Array.Resize(ref myArray, myNewSize);
// Test: 1
Console.Write(myArray.Length);
答案 1 :(得分:1)
realloc
将尝试进行inplace resize - 但它保留将整个内容复制到其他位置并返回完全不同的指针的权利。
.NET的List<T>
类几乎都暴露了相同的外向行为 - 如果您发现自己经常更改数组大小,那么您应该使用它。它隐藏了您的实际数组引用,以便更改在所有对同一列表的引用中传播。当您从末尾删除项目时,只有列表的长度发生变化,而内部数组保持不变 - 避免复制。
它没有释放内存(您可以随时使用Capacity = XXX
明确地执行此操作,但这会生成数组的新副本),但是再次,除非您& #39;重新使用大型数组,realloc
也没有 - 如果您正在使用大型阵列,yada,yada - 我们已经在那里:)
realloc
在.NET无论如何的内存模型中都没有意义 - 堆随着时间的推移不断收集和压缩。因此,如果您只是在修剪阵列时尝试使用它来避免副本,同时还要保持较低的内存使用率......不要打扰。在下一次堆压缩时,将移动数组上方的整个内存以填充空白。即使可以执行realloc
,你只需要复制数组就可以将数组保存在旧生存堆中 - 这不一定是你想要的
答案 2 :(得分:1)
BCL中的数组类型都不支持您想要的内容。话虽这么说 - 你可以实现自己的类型,以支持你所需要的。它可以由标准数组支持,但是会实现自己的Length和indexer属性,这些属性会“隐藏”你的数组部分。
public class MyTruncatableArray<T>
{
private T[] _array;
private int _length;
public MyTruncatableArray(int size)
{
_array = new T[size];
_length = size;
}
public T this[int index]
{
get
{
CheckIndex(index, _length);
return _array[index];
}
set
{
CheckIndex(index, _length);
_array[index] = value;
}
}
public int Length
{
get { return _length; }
set
{
CheckIndex(value);
_length = value;
}
}
private void CheckIndex(int index)
{
this.CheckIndex(index, _array.Length);
}
private void CheckIndex(int index, int maxValue)
{
if (index < 0 || index > maxValue)
{
throw new ArgumentException("New array length must be positive and lower or equal to original size");
}
}
}
这实际上取决于究竟需要什么。 (例如,您是否需要截断以便您可以更轻松地从代码中使用它。或者是perf / GC /内存消耗是一个问题?如果后者是这种情况 - 您是否执行任何测量证明标准Array.Resize方法无法使用为你的情况?)