目前,我正在处理一个包含大量遗留代码的项目,其中包括使用非通用集合,例如.NET ArrayList
,{{1}等等。
我知道在原型类型中使用这些类型的集合是一个糟糕的想法,在性能方面的考虑因素中可以表现为mentioned by List's documentation"部分(我在最后通过一个快速且极其简单的LinqPad查询确认了这一点 - 最后附上)。
乍一看似乎没有任何问题在进行某种搜索/替换操作来替换这些旧的集合。但是因为它会影响代码库的很大一部分,所以我担心会有HashTable
不表现为"期望"的副作用,给定{{1应用程序已经依赖的特定行为。
之前有没有人进行过大规模的转换?如果是,是否存在.NET文档中未提及的细微问题?
List<T>
我机器上的输出:
ArrayList
多次运行几乎总是显示void Main()
{
var size = 1000000;
var array = new int[size];
var list = new List<int>();
var arrayList = new ArrayList();
Console.WriteLine("Testing " + size + " insertions...");
Console.WriteLine();
var stopwatch = Stopwatch.StartNew();
for (var i = 0; i < size; i++)
{
array[i] = i;
}
stopwatch.Stop();
Console.WriteLine("int[]: " + stopwatch.Elapsed.TotalMilliseconds + "ms");
stopwatch.Restart();
for (var i = 0; i < size; i++)
{
list.Add(i);
}
stopwatch.Stop();
Console.WriteLine("List<int>: " + stopwatch.Elapsed.TotalMilliseconds + "ms");
stopwatch.Restart();
for (var i = 0; i < size; i++)
{
arrayList.Add(i);
}
stopwatch.Stop();
Console.WriteLine("ArrayList: " + stopwatch.Elapsed.TotalMilliseconds + "ms");
}
比Testing 1000000 insertions...
int[]: 3,1063ms
List<int>: 7,2291ms
ArrayList: 111,5214ms
或ArrayList
慢一个数量级。
答案 0 :(得分:1)
早期,我的一项工作是将ArrayLists换成通用计数器部件。我建议不要破坏大型代码库:不要进行搜索/替换。
只有“升级”时:
对于小于1000000的长度,ArrayList性能有很大不同。理论上,是的,ArrayList很糟糕。但是在 practice 中,如果95%的ArrayLists的长度为&lt; 100,甚至可以&lt; 1000,您的应用程序将看不到显着的性能提升,并且您可能会通过更换这些偶然的ArrayLists来破坏代码库的稳定性。
当n接近1000000时,由于知道ArrayLists非常慢,我建议继续寻找5%的ArrayLists,其中n接近“慢”限制,并努力将它们交换出去。如果条件1也满足,则仅换出。根据我的经验,如果从现在起6个月后你的应用程序开始出现奇怪的崩溃,那就完全不值得ms甚至几秒钟的性能提升,因为你没有意识到触及ArrayList的东西并要求它成为一个ArrayList。
答案 1 :(得分:1)
请注意ArrayList
对于值类型来说只会慢得多。例如,如果你有ArrayList
个字符串,那么差异就不会很大 - 性能上。当然,List<string>
更加类型安全。
您在编译时会发现一些差异。例如:
var list = new ArrayList();
list.Add(3);
list[0].ToString(); // Works fine
var list = new List<string>();
list.Add(3); // Fails
但是,在编译期间应该很容易修复和查找。 List<T>
不会产生ArrayList
没有的运行时条件。反过来有很多问题,但List<T>
比ArrayList
更严格 - 在编译期间。
您的大部分问题都出在ArrayList
包含没有共同祖先的类型的地方。用ArrayList
替换List<object>
并不会对你有多大帮助。在某些情况下,这可能是ArrayList
的合法使用。其中的一个子集是接受ArrayList
的方法,并对此做一些通用的方法。根据使用情况,您将需要分离代码,或者使方法也是通用的。
如果您的类型派生自ArrayList
,将其更改为List<T>
可能会给您一些可疑的方法重载 - 其中许多只会产生警告,所以如果您在这种情况下,注意警告,而不仅仅是错误。
您打算如何进行全球搜索&amp;更换?您是否手动浏览ArrayList
的每个外观并将其转换为给定的特定List<T>
?这应该是非常安全的。