【发布时间】:2011-06-17 23:14:58
【问题描述】:
声明后可以更改数组大小吗?
如果没有,是否有任何替代数组的方法?
我不想创建一个大小为 1000 的数组,但是我在创建它时不知道数组的大小。
【问题讨论】:
声明后可以更改数组大小吗?
如果没有,是否有任何替代数组的方法?
我不想创建一个大小为 1000 的数组,但是我在创建它时不知道数组的大小。
【问题讨论】:
您可以使用Array.Resize(),记录在MSDN。
但是,是的,我同意 Corey 的观点,如果您需要动态大小的数据结构,我们有 Lists 来解决这个问题。
重要提示:Array.Resize() 不会调整数组的大小(方法名称具有误导性),它会创建一个新数组并仅替换您传递给方法的 reference。
一个例子:
var array1 = new byte[10];
var array2 = array1;
Array.Resize<byte>(ref array1, 20);
// Now:
// array1.Length is 20
// array2.Length is 10
// Two different arrays.
【讨论】:
List<T> 在后台使用数组,因此在 C# 中使用数组的理由很少。可以使用以下构造函数将列表初始化为合适的大小:msdn.microsoft.com/en-us/library/dw8e0z9z.aspx。但是,是的,如果您的心是阵列,最好尽可能不频繁地调整它们的大小。
List<Int> 在幕后使用 Array.Resize。它在幕后使用了一般(尽管不是普遍)的最佳算法,其中每次增长数组时,它都会将数组的大小加倍。除非您正在开发高性能实时系统(例如高速交易或机械控制系统),否则您应该使用 List<Int>,因为它“足够好”并且更易于维护。
不,请尝试使用强类型 List。
例如:
而不是使用
int[] myArray = new int[2];
myArray[0] = 1;
myArray[1] = 2;
你可以这样做:
List<int> myList = new List<int>();
myList.Add(1);
myList.Add(2);
列表使用数组来存储数据,因此您可以通过 LinkedList 方便地获得数组的速度优势,因为您可以添加和删除项目,而不必担心必须手动更改其大小.
这并不意味着数组的大小(在本例中为 List)没有改变 - 因此手动强调这个词。
一旦您的数组达到其预定义的大小,JIT 就会在堆上分配一个两倍大小的新数组,并复制您现有的数组。
【讨论】:
您可以在 .net 3.5 及更高版本中使用 Array.Resize()。此方法分配一个指定大小的新数组,将元素从旧数组复制到新数组,然后用新数组替换旧数组。
(因此您需要为两个数组提供可用的内存,因为这可能在幕后使用Array.Copy)
【讨论】:
是的,可以调整数组的大小。例如:
int[] arr = new int[5];
// increase size to 10
Array.Resize(ref arr, 10);
// decrease size to 3
Array.Resize(ref arr, 3);
如果使用 CreateInstance() 方法创建数组,则 Resize() 方法不起作用。例如:
// create an integer array with size of 5
var arr = Array.CreateInstance(typeof(int), 5);
// this not work
Array.Resize(ref arr, 10);
数组大小不是动态的,即使我们可以调整它的大小。如果你想要一个动态数组,我认为我们可以使用泛型 List 来代替。
var list = new List<int>();
// add any item to the list
list.Add(5);
list.Add(8);
list.Add(12);
// we can remove it easily as well
list.Remove(5);
foreach(var item in list)
{
Console.WriteLine(item);
}
【讨论】:
在 C# 中,不能动态调整数组的大小。
一种方法是使用
System.Collections.ArrayList 改为
native array。
另一个(更快)的解决方案是 重新分配数组 不同的大小和复制 旧数组的内容到新的 数组。
通用函数 resizeArray(如下)可用于执行此操作。
public static System.Array ResizeArray (System.Array oldArray, int newSize)
{
int oldSize = oldArray.Length;
System.Type elementType = oldArray.GetType().GetElementType();
System.Array newArray = System.Array.CreateInstance(elementType,newSize);
int preserveLength = System.Math.Min(oldSize,newSize);
if (preserveLength > 0)
System.Array.Copy (oldArray,newArray,preserveLength);
return newArray;
}
public static void Main ()
{
int[] a = {1,2,3};
a = (int[])ResizeArray(a,5);
a[3] = 4;
a[4] = 5;
for (int i=0; i<a.Length; i++)
System.Console.WriteLine (a[i]);
}
【讨论】:
将此方法用于字节数组:
最初:
byte[] bytes = new byte[0];
根据需要(需要提供原长度以进行延长):
Array.Resize<byte>(ref bytes, bytes.Length + requiredSize);
重置:
Array.Resize<byte>(ref bytes, 0);
类型列表法
最初:
List<byte> bytes = new List<byte>();
需要时:
bytes.AddRange(new byte[length]);
释放/清除:
bytes.Clear()
【讨论】:
【讨论】:
请改用List<T>。例如,而不是整数数组
private int[] _myIntegers = new int[1000];
使用
private List<int> _myIntegers = new List<int>();
稍后
_myIntegers.Add(1);
【讨论】:
在 C# 中,Array.Resize 是将任何数组调整为新大小的最简单方法,例如:
Array.Resize<LinkButton>(ref area, size);
在这里,我想调整 LinkButton 数组的数组大小:
<LinkButton> = 指定数组类型ref area = ref 是关键字,'area' 是数组名称size = 新大小数组
【讨论】:
private void HandleResizeArray()
{
int[] aa = new int[2];
aa[0] = 0;
aa[1] = 1;
aa = MyResizeArray(aa);
aa = MyResizeArray(aa);
}
private int[] MyResizeArray(int[] aa)
{
Array.Resize(ref aa, aa.GetUpperBound(0) + 2);
aa[aa.GetUpperBound(0)] = aa.GetUpperBound(0);
return aa;
}
【讨论】:
当您想要添加/删除数据时,请使用列表(其中 T 是任何类型或对象),因为调整数组大小的成本很高。您可以阅读有关Arrays considered somewhat harmful 的更多信息,而可以将列表添加到新记录可以附加到末尾。它会根据需要调整其大小。
可以通过以下方式初始化列表
使用集合初始化器。
List<string> list1 = new List<string>()
{
"carrot",
"fox",
"explorer"
};
将 var 关键字与集合初始化器一起使用。
var list2 = new List<string>()
{
"carrot",
"fox",
"explorer"
};
使用新数组作为参数。
string[] array = { "carrot", "fox", "explorer" };
List<string> list3 = new List<string>(array);
在构造函数中使用容量并赋值。
List<string> list4 = new List<string>(3);
list4.Add(null); // Add empty references. (Not Recommended)
list4.Add(null);
list4.Add(null);
list4[0] = "carrot"; // Assign those references.
list4[1] = "fox";
list4[2] = "explorer";
对每个元素使用 Add 方法。
List<string> list5 = new List<string>();
list5.Add("carrot");
list5.Add("fox");
list5.Add("explorer");
因此,对于一个对象列表,您可以分配和分配与列表初始化内联的对象的属性。对象初始化器和集合初始化器共享相似的语法。
class Test
{
public int A { get; set; }
public string B { get; set; }
}
用集合初始化器初始化列表。
List<Test> list1 = new List<Test>()
{
new Test(){ A = 1, B = "Jessica"},
new Test(){ A = 2, B = "Mandy"}
};
用新对象初始化列表。
List<Test> list2 = new List<Test>();
list2.Add(new Test() { A = 3, B = "Sarah" });
list2.Add(new Test() { A = 4, B = "Melanie" });
【讨论】:
这对我来说很有效,可以从类数组创建动态数组。
var s = 0;
var songWriters = new SongWriterDetails[1];
foreach (var contributor in Contributors)
{
Array.Resize(ref songWriters, s++);
songWriters[s] = new SongWriterDetails();
songWriters[s].DisplayName = contributor.Name;
songWriters[s].PartyId = contributor.Id;
s++;
}
【讨论】:
如果您确实需要将其重新转换为数组,我发现将array 转换为list 最简单,展开列表然后将其转换回array。
string[] myArray = new string[1] {"Element One"};
// Convert it to a list
List<string> resizeList = myArray.ToList();
// Add some elements
resizeList.Add("Element Two");
// Back to an array
myArray = resizeList.ToArray();
// myArray has grown to two elements.
【讨论】:
如果您不能使用Array.Reset(变量不是本地变量),那么Concat & ToArray 会有所帮助:
anObject.anArray.Concat(new string[] { newArrayItem }).ToArray();
【讨论】:
使用通用列表 (System.Collections.Generic.List)。
【讨论】: