将旧版.NET集合迁移到其通用对应项

时间:2015-02-24 14:53:40

标签: c# .net performance arraylist generic-collections

目前,我正在处理一个包含大量遗留代码的项目,其中包括使用非通用集合,例如.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慢一个数量级。

2 个答案:

答案 0 :(得分:1)

早期,我的一项工作是将ArrayLists换成通用计数器部件。我建议不要破坏大型代码库:不要进行搜索/替换。

只有“升级”时:

  1. 您可以看到ArrayList的整个范围以及“触及”它的所有内容。
  2. 会有实际性能提升。
  3. 对于小于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>?这应该是非常安全的。