代码之家  ›  专栏  ›  技术社区  ›  kemiller2002

泛型与数组列表

  •  15
  • kemiller2002  · 技术社区  · 17 年前

    我在这里工作的系统是在.NET 2.0之前编写的,没有泛型的好处。它最终被更新为2.0,但由于时间限制,没有任何代码被重构。代码使用数组列表等将事物存储为对象的地方有很多。

    从性能角度来看,将代码更改为使用泛型有多重要?我知道,从表演的角度来看,拳击和拆箱等,它是低效的,但从改变它,真正会有多少表演增益?泛型是否可以在未来的基础上使用,或者是否有足够的性能变化需要良心上的努力来更新旧代码?

    12 回复  |  直到 17 年前
        1
  •  14
  •   Rory    17 年前

    从技术上讲,仿制药的表现更好。但是,除非性能非常重要,而且您已经在其他领域进行了优化,否则您可能会通过在其他地方花费时间来获得更好的改进。

    我建议:

    • 继续使用泛型。
    • 如果您有可靠的单元测试,那么在触摸代码时重构为泛型。
    • 花其他时间进行重构/度量,这将显著提高性能(数据库调用、更改数据结构等),而不是在这里或那里花费几毫秒。

    当然,除了性能以外,还有其他原因需要改变为仿制药:

    • 不易出错,因为您有类型的编译时检查
    • 更具可读性的是,您不需要在整个地方强制转换,很明显,集合中存储的是什么类型
    • 如果你继续使用仿制药,那么在任何地方使用仿制药都会更干净。
        2
  •  8
  •   torial    17 年前

    这是我从100kb文件中对字符串进行100000次简单解析得到的结果。通用列表(char)花了612.293秒在文件中遍历100000次。 arraylist花了2880.415秒浏览文件100000次。这意味着在这种情况下(作为你的里程 vary)通用列表(char)快4.7倍。

    下面是我运行了100000次的代码:

    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
    
        3
  •  4
  •   Ben Hoffstein    17 年前

    唯一确定的方法是使用类似于dottrace的工具来分析代码。

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

    装箱/拆箱在您的特定应用程序中可能是微不足道的,不值得重构。接下来,由于编译时类型的安全性,您仍然应该考虑使用泛型。

        4
  •  3
  •   Peter    17 年前

    泛型,无论是Java还是.NET,都应该用于设计和类型安全,而不是用于性能。Autoboxing不同于泛型(本质上是隐式对象到基元的转换),正如您所提到的,如果要进行大量的算术或其他操作,从而导致重复的隐式对象创建/销毁导致性能下降,则不应使用它们代替基元。

    总的来说,我建议继续使用,并且仅在需要为类型安全/设计目的而清理现有代码时更新现有代码,而不是性能。

        5
  •  1
  •   Rick Minerich    17 年前

    这取决于,最好的答案是分析代码并查看。我喜欢aqtime,但有很多软件包。

    一般来说,如果大量使用arraylist,将其转换为通用版本可能是值得的。实际上,很可能您甚至无法测量性能差异。拳击和拆箱是额外的步骤,但现代计算机如此之快,几乎没有任何区别。因为arraylist实际上只是一个普通的带有漂亮包装的数组,所以您可能会看到从更好的数据结构选择中获得更多的性能(arraylist.remove是o(n)!)而不是通过向泛型的转换。

    编辑:非法程序员有一个很好的观点,你仍将与泛型拳击和拆箱,它只是隐式发生。不过,所有关于检查casting和“is/as”关键字的异常和空值的代码都会有一些帮助。

        6
  •  0
  •   hova    17 年前

    最大的收益,你会发现在维护阶段。泛型更容易处理和更新,而不必处理转换和强制转换问题。如果这是您不断访问的代码,那么一定要付出努力。如果这是多年来没有接触过的代码,我不会真的麻烦。

        7
  •  0
  •   Tim Frey    17 年前

    自动装箱/拆箱与仿制药有什么关系?这只是一个类型安全问题。对于非泛型集合,需要显式转换回对象的实际类型。使用泛型,您可以跳过这一步。我不认为有任何不同的表现方式。

        8
  •  0
  •   echoblaze    17 年前

    我以前的公司确实考虑过这个问题。我们采用的方法是:如果重构很容易,那么就进行重构;如果不容易(即它会接触到太多的类),那么就将其留到以后的时间。这实际上取决于您是否有时间来做,或者是否有更重要的项目需要编码(即,您应该为客户机实现的特性)。

    同样,如果您没有为客户机做什么工作,那么继续进行并花时间重构。它将提高代码的可读性。

        9
  •  0
  •   Tom Carr    17 年前

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

    如果你的数组只是到处撒,那么清理它可能不是什么大问题,但也不会对整体性能产生很大影响。

    如果您在整个代码中使用了大量的数组列表,并且要替换它们(这可能会影响您的日程安排),那么您可以采用一种如果触摸它就会改变它的方法。

    不过,最重要的是,由于你从仿制药中得到了强大的输入,仿制药更容易阅读,而且在整个应用程序中更稳定。您不仅可以看到性能的提高,还可以看到代码的可维护性和稳定性的提高。如果你能快点做,我会说快点做。

    如果你能从产品所有者那里得到认可,我建议你把它清理干净。你以后更喜欢你的代码。

        10
  •  0
  •   Mark Bessey    17 年前

    如果arraylist中的实体是对象类型,那么不将它们强制转换为正确的类型会有一些收获。如果它们是值类型(像int32这样的结构或原语),那么装箱/拆箱过程会增加很多开销,并且泛型集合应该更快。

    Here's an MSDN article on the subject

        11
  •  0
  •   Dror Helper    17 年前

    泛型有更好的性能,特别是如果您将使用值类型(int、bool、struct等),您将获得显著的性能提升。

    1. 将arraylist与值类型一起使用会导致装箱/拆箱,如果执行数百次,则装箱/拆箱速度明显比使用泛型列表慢。

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

    我写了关于 here .

        12
  •  0
  •   Simon P    17 年前

    使用泛型还意味着,如果您想在以后的C版本中利用Linq之类的东西,那么您的代码将更加简单和易于使用。