Vb.net 你会选择Linq而不是Forloops吗?

Vb.net 你会选择Linq而不是Forloops吗?,vb.net,linq,for-loop,Vb.net,Linq,For Loop,给定包含如下两列的datatable: Private Function CreateDataTable() As DataTable Dim customerTable As New DataTable("Customers") customerTable.Columns.Add(New DataColumn("Id", GetType(System.Int32))) customerTable.Columns.Add(New DataColumn("Name", Ge

给定包含如下两列的datatable:

Private Function CreateDataTable() As DataTable
    Dim customerTable As New DataTable("Customers")
    customerTable.Columns.Add(New DataColumn("Id", GetType(System.Int32)))
    customerTable.Columns.Add(New DataColumn("Name", GetType(System.String)))

    Dim row1 = customerTable.NewRow()
    row1.Item("Id") = 1
    row1.Item("Name") = "Customer 1"
    customerTable.Rows.Add(row1)

    Dim row2 = customerTable.NewRow()
    row2.Item("Id") = 2
    row2.Item("Name") = "Customer 2"
    customerTable.Rows.Add(row2)

    Dim row3 = customerTable.NewRow()
    row3.Item("Id") = 3
    row3.Item("Name") = "Customer 3"
    customerTable.Rows.Add(row3)

    Return customerTable
End Function
是否使用此代码段检索包含所有Id的(整数)列表:

Dim table = CreateDataTable()

Dim list1 As New List(Of Integer)

For i As Integer = 0 To table.Rows.Count - 1
    list1.Add(CType(table.Rows(i)("Id"), Integer))
Next
或者更确切地说是这个:

Dim list2 = (From r In table.AsEnumerable _
             Select r.Field(Of Integer)("Id")).ToList()
这不是一个关于是否使用.Field(Of Integer)、CType、CInt、DirectCast等将Id列强制转换为整数的问题,而是一个关于是否像主题所暗示的那样选择Linq而不是forloops的问题


对于那些感兴趣的人:我对这两个版本进行了一些迭代,得到了以下性能图:

纵轴显示代码将行的ID转换为横轴上显示行数的通用列表所用的毫秒数。蓝线来自命令式方法(forloop),红线来自声明性代码(linq)



无论您通常选择哪种方式:为什么您选择那种方式而不是另一种方式?

只要有可能,我都喜欢声明式编程方式而不是命令式编程。使用声明性方法时,CLR可以根据机器的特性优化代码。例如,如果它有多个核心,它可以并行执行,而如果使用命令For循环,则基本上锁定了这种可能性。今天可能没有什么大的区别,但我认为将来会出现越来越多的像PLINQ这样的扩展,以实现更好的优化。

我最近发现自己怀疑自己是否完全被LINQ宠坏了。是的,我现在一直在使用它从所有种类的集合中挑选所有种类的东西。

我避免使用linq,除非它对可读性有很大帮助,因为它完全破坏了编辑和继续


当他们解决这个问题时,我可能会开始更多地使用它,因为我确实非常喜欢某些东西的语法。

我开始这样做,但发现在某些情况下,我使用这种方法节省了时间:

for (var i = 0, len = list.Count; i < len; i++) { .. }
for(var i=0,len=list.Count;i

不一定在所有情况下,但有些情况下。大多数扩展方法都使用foreach查询方法。

对于我所做的几乎所有事情,我都得出结论,LINQ已经足够优化了。如果我手工制作一个for循环,它会有更好的性能,但是在我们通常谈论的大计划中,它是毫秒级的。由于我很少遇到那些毫秒会产生任何影响的情况,我发现更重要的是要有清晰意图的可读代码。我宁愿打一个慢50毫秒的电话,也不愿有人过来把它完全打断

Resharper有一个很酷的功能,可以标记循环并将其转换为Linq表达式。我将把它翻到Linq版本,看看这是否会损害或有助于可读性。如果Linq表达式更清楚地传达了代码的意图,我会同意。如果Linq表达式不可读,我将返回到foreach版本

对我来说,大多数性能问题都不能与可读性相比

清晰胜过聪明


在上面的例子中,我将使用Linq版本,因为它清楚地解释了意图,并且也阻止了人们在循环中意外添加副作用。

我尝试遵循以下规则:

  • 每当我只是查询(过滤、投影等)集合时,请使用LINQ
  • 一旦我真的“做”了一些有结果的事情(即,引入副作用),我就会使用for循环
在本例中,我将使用LINQ

此外,我总是尝试将“查询定义”与“查询评估”分开:

Dim query = From r In table.AsEnumerable() 
            Select r.Field(Of Integer)("Id")

Dim result = query.ToList()

这清楚地表明了何时(在本例中是在内存中)对查询进行求值。

真的是这样吗?我记得不久前读过一篇博客文章。你可以在这里找到它:。基本结论是这样的:“很自然,它的性能不如传统的命令式循环,优化也可能更少”。这个结果来自一个运行时比较,结果是linq查询的性能比命令式方法差50倍。我发现性能的参数不是很好,我认为您永远不必期望linq查询的性能在没有任何代码更改的情况下大幅提高,因为系统必须向后兼容。然而,由于可读性和可维护性,我更喜欢声明式编程方式。LINQ查询在表达意图方面要好得多。我支持这一点。我还认为声明性linq查询更具可读性,因此更易于维护。然而,Darin提出了代码优化的论点,我想知道编译器是否真的能够比命令式代码更好地优化基于声明式语法的代码。@Darin:你在Reflector中打开过Linq查询吗?LINQ实际上并不是在LINQ to对象的结果二进制文件中发出的。@Billy,是的,我在Reflector中打开了一个LINQ查询。它是基于被调用的扩展方法,所以我不理解你关于LINQ没有在结果二进制中发出的论点。你对LINQ使用调试器做了一个公平的陈述。然而,我喜欢扭转这种局面:我使用LINQ,除非我必须调试该代码。在那种情况下,我(暂时)重写了那句话。然而,通常情况下,单元测试可以节省我的时间,这正是我所做的。然而,因为我们已经有“百万”个地方使用循环,这是每个人都习惯的,所以我还是保持原样。