generics与数组列表

我在这里工作的系统是在.net 2.0之前编写的,并没有使用generics。 它最终更新为2.0,但由于时间限制,没有任何代码被重构。 在许多地方,代码使用ArraysLists等将事物存储为对象。

从性能角度来看,将代码更改为使用generics有多重要? 我从性能的角度来看,拳击和拆箱等等,这是低效的,但实际上有多少性能增益会改变呢? 仿制药是否可以在前进的基础上使用,或者是否有足够的性能变化,以便为更新旧代码做出良心努力?

从技术上讲,仿制药的性能,正如你所说,更好。 但是,除非性能非常重要并且您已经在其他领域进行了优化,否则您可能会花时间在其他地方获得更好的改进。

我会建议:

  • 继续使用generics。
  • 如果您有可靠的unit testing,那么在触摸代码时重构generics
  • 花费其他时间进行重构/测量,这将显着提高性能(数据库调用,更改数据结构等),而不是几毫秒。

当然除了性能之外还有其他原因可以改为generics:

  • 因为你有类型的编译时检查,所以不容易出错
  • 更具可读性,您不需要遍布整个地方,很明显,什么类型存储在集合中
  • 如果你正在使用generics,那么在任何地方使用它都会更清洁

这是我从100KB文件中简单解析一个字符串100,000次得到的结果。 通用列表(of char)在文件中花费了612.293秒来完成100,000次。 ArrayList花了2,880.415秒来完成文件的100,000次。 这意味着在这种情况下(因为您的里程有所不同),通用列表(Of char)的速度要快4.7倍。

这是我经历了100,000次的代码:

Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run Dim genList As New ArrayList For Each ch As Char In strToProcess.ToCharArray genList.Add(ch) Next Dim dummy As New System.Text.StringBuilder() For i As Integer = 0 To genList.Count - 1 dummy.Append(genList(i)) Next End Sub Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run Dim genList As New List(Of Char) For Each ch As Char In strToProcess.ToCharArray genList.Add(ch) Next Dim dummy As New System.Text.StringBuilder() For i As Integer = 0 To genList.Count - 1 dummy.Append(genList(i)) Next End Sub 

唯一可以确定的方法是使用dotTrace之类的工具来分析代码。

http://www.jetbrains.com/profiler/

拳击/拆箱可能在您的特定应用程序中是微不足道的,并且不值得重构。 outlook未来,由于编译时类型的安全性,您仍应考虑使用generics。

generics,无论是Java还是.NET,都应该用于设计和类型安全,而不是性能。 自动装箱与通用装置(基本上是隐式对象到原始转换)不同,正如您所提到的,如果存在大量算术或其他操作会导致重复性能损失,则不应使用它们代替基元。隐式对象创建/销毁。

总的来说,我建议使用前进,只更新现有代码,如果需要清除类型安全/设计目的,而不是性能。

这取决于,最好的答案是分析您的代码并查看。 我喜欢AQTime,但是存在许多包。

通常,如果正在使用ArrayList,则可能值得将其切换为通用版本。 实际上,你很可能甚至无法衡量性能差异。 拳击和拆箱是额外的步骤,但现代计算机是如此之快,几乎没有差别。 由于ArrayList实际上只是一个带有漂亮包装器的普通数组,因此您可能会看到从更好的数据结构选择(ArrayList.Remove是O(n)!)获得的性能远远高于转换为generics。

编辑:Outlaw程序员有一个好点,你仍然会使用generics装箱和拆箱,它只是隐含地发生。 检查exception的所有代码以及来自“is / as”关键字的空值都会有所帮助。

最大的收获,你会发现在维护阶段。 generics更易于处理和更新,而无需处理转换和转换问题。 如果这是您不断访问的代码,那么一定要付出努力。 如果这是几年未被触及的代码,我真的不会打扰。

自动装箱/拆箱与仿制药有什么关系? 这只是一个类型安全问题。 对于非generics集合,您需要显式地转换回对象的实际类型。 使用generics,您可以跳过此步骤。 我不认为这种或那种方式存在性能差异。

我的老公司实际上考虑过这个问题。 我们采取的方法是:如果它很容易重构,那就去做; 如果没有(即它会触及太多的课程),请留待以后。 这实际上取决于你是否有时间去做,或者是否有更重要的项目要编码(即你应该为客户实现的function)。

然后,如果你没有为客户做某事,那就继续花点时间重构。 它将为您自己提高代码的可读性。

取决于您的代码中有多少。 如果您在UI中绑定或显示大型列表,您可能会看到性能的巨大提升。

如果您的ArrayList只是随处可见,那么将它清理干净可能不是什么大问题,但也不会对整体性能产生太大影响。

如果您在整个代码中使用了大量的ArrayLists,那么替换它们(可能会影响您的日程安排的事情)将是一个很大的不足之处,那么您可以采用一种if-you-touch-it-change-it方法。

但主要的是,Generics更易于阅读,并且由于您从中获得了强大的输入,因此在整个应用程序中更加稳定。 您不仅可以从性能上获得收益,还可以从代码维护性和稳定性中获益。 如果你能快点做到,我会说这样做。

如果您可以从产品负责人那里购买,我建议您将其清理干净。 之后你更喜欢你的代码。

如果ArrayLists中的实体是Object类型,那么从未将它们转换为正确的类型可以获得一点点。 如果它们是Value类型(结构或原语如Int32),那么装箱/拆箱过程会增加很多开销,而通用集合应该快得多。

这是关于这个主题的MSDN文章

generics具有更好的性能,特别是如果你将使用值类型(int,bool,struct等),你将获得显着的性能提升。

  1. 使用具有值类型的Arraylist导致装箱/拆箱,如果完成几百次,则实际上比使用通用列表慢。

  2. 将值类型存储为对象时,每个项目最多可存储四个时间内存。 虽然这个数量不会耗尽您的RAM,但较小的缓存内存可能包含较少的项目,这意味着在迭代长集合时,会有许多从主内存到缓存的副本会降低您的应用程序速度。

我在这里写过。

如果你想在后来的c#版本中利用linq之类的东西,那么使用generics也意味着你的代码将更简单易用。