Vb.net 其中().Count()与Count()的比较

Vb.net 其中().Count()与Count()的比较,vb.net,performance,linq,list,Vb.net,Performance,Linq,List,下面是我的类的相关部分的摘录,它继承自List(of T)。查看SelectedObjects和SelectedCount属性。出于性能原因,我添加了SelectedCount,但现在我想知道它是否比SelectedObjects.Count()更好 我的理论是,Where(predicate).Count()和Count(predicate)都需要迭代列表,因此不会有太大的差异。另外,由于我没有在Where()上执行任何ToList()或ToArray(),因此我不确定对其调用Count()是

下面是我的类的相关部分的摘录,它继承自
List(of T)
。查看
SelectedObjects
SelectedCount
属性。出于性能原因,我添加了
SelectedCount
,但现在我想知道它是否比
SelectedObjects.Count()
更好

我的理论是,
Where(predicate).Count()
Count(predicate)
都需要迭代列表,因此不会有太大的差异。另外,由于我没有在
Where()
上执行任何
ToList()
ToArray()
,因此我不确定对其调用
Count()
是否能够利用内置的
Count
属性


因此,我应该保留还是删除
SelectedCount
属性?

正如Jon Skeet在评论中所说的,最好的方法是测量。 但是,如果您同时使用
SelectedObjects
,我会删除
CountObjects
。原因如下:

  • 如果您的
    IEnumerable
    是内存中的列表,那么正如您提到的
    CountObjects
    将再次检查原始列表。如果您已经调用了
    SelectedObjects
    ,并且结果是一个变量,那么调用
    Count
    只会调用列表中的一个属性,并立即给出对象的数量,而不会再次循环。如果您没有调用
    SelectedObjects
    ,那么我认为调用
    .Where(…).Count()
    并不比
    .Count(…)
    慢。这是你应该测试的东西

  • 如果您
    IEnumerable
    是一个
    IQueryable
    ,那么它要么已经被物化了,在这种情况下它并不重要,要么-如果它还没有被物化-那么我希望调用
    。其中(…).Count()
    将转换为相同的
    选择Count(*)
    查询。同样,这是你应该测试的东西

我用一些(相当幼稚的)代码来计时:

我得到的结果是

countwhere/Count
-------------------
3494    3624
3484    3612
3523    3617
3522    3609
3500    3623
3493    3631
3536    3620
3541    3682
3621    3633
3515    3686   

平均而言,使用
Where/Count
所花费的时间延长了约4%(在本例中,平均延长了110毫秒)。因此,只做
Count
可能会带来性能上的好处。然而,您需要首先确认这在您的特定场景/环境中是正确的。看看埃里克·利珀特的《如何做到这一点的好建议》。

如果你想知道出于性能原因做某件事是否值得,那么有一个显而易见的方法可以找到:测量它。@JonSkeet:没错,但我也想让专业人士对我的理论进行评估。那么你为什么不现在进行测量,并将其添加到问题中。。。以及尝试确定
Count
所花费的时间在应用程序中是否真的很重要。在
IQueryable
的情况下,重要的是要认识到
.Where
方法和
.Count
方法在这两种方法中是非常不同的。依赖继承/多态性将导致.net加载您的表,然后对对象进行计数。
Public Class DrawingObjectsList
    Inherits List(Of DrawingObjectBase)

  Friend ReadOnly Property DOsOfCurrentFace As IEnumerable(Of DrawingObjectBase)
    Get
        Return Me.Where(Function(DObj) DObj.Face = mFace)
    End Get
  End Property

  Public ReadOnly Property SelectedObjects() As IEnumerable(Of DrawingObjectBase)
    Get
        Return DOsOfCurrentFace.Where(Function(DObj) DObj.IsSelected = True)
    End Get
  End Property

  Public ReadOnly Property SelectedCount() As Integer
    Get
        Return DOsOfCurrentFace.Count(Function(DObj) DObj.IsSelected = True)
    End Get
  End Property
End Class
Dim r = New Random()
Dim sw As Stopwatch
Dim list = Enumerable.Range(0, 100000000).Select(Function(x) r.Next)

sw = Stopwatch.StartNew()
list.Count(Function(x) x Mod 2 = 0)
Console.WriteLine(sw.ElapsedMilliseconds)

sw = Stopwatch.StartNew()
Dim x = list.Where(Function(x) x Mod 2 = 0).Count()
Console.WriteLine(sw.ElapsedMilliseconds)