这是我的类中继承自List(Of T)
的相关部分的摘录。看看SelectedObjects
和SelectedCount
属性。出于性能原因,我添加了SelectedCount
,但现在想知道它是否比SelectedObjects.Count()
更好。
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
我的理论是,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
那么它要么已经实现,在这种情况下没关系,要么 - 如果它没有实现 - 那么我希望对.Where(...).Count()
的调用将转换为与.Count(...)
相同的SELECT COUNT(*)
查询。同样,这是您应该测试的内容。
我用一些(相当幼稚的)代码计时:
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)
我得到的结果是
Count Where/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
可能会对性能有好处。但是,您需要首先确认这在您的特定方案/环境中成立。查看 Eric Lippert 的 C# 性能基准测试错误,了解如何做到这一点的好提示。