以下是我班级相关部分的摘录,该部分继承自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)
都需要迭代List,因此不应该有任何相当大的差异。此外,由于我未在ToList()
上执行任何ToArray()
或Where()
,因此我不确定在其上调用Count()
是否可以利用内置{ {1}}属性与否。
我应该保留还是删除Count
属性?
答案 0 :(得分:0)
正如Jon Skeet在评论中所说,最好的方法是衡量。
但是,如果您 使用SelectedObjects
,我会删除CountObjects
。原因如下:
如果您的IEnumerable
是内存列表,那么当您提到CountObjects
时,将再次浏览原始列表。如果您已经调用SelectedObjects
并将结果保存在变量中,则调用Count
将只调用列表中的属性并立即为您提供对象数,而无需再次循环。如果您还没有拨打SelectedObjects
,那么我认为调用.Where(...).Count()
比<{1}} 更慢。这是你应该测试的东西。
如果您.Count(...)
是IEnumerable
,那么它已经实现了,在这种情况下无关紧要,或者 - 如果它没有实现 - 那么我希望对IQueryable
的来电将转换为.Where(...).Count()
将会发出的SELECT COUNT(*)
查询。同样,这是你应该测试的东西。
答案 1 :(得分:0)
我用一些(相当幼稚的)代码计时:
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# Performance Benchmark Mistakes,了解如何做到这一点的好方法。