2014-04-29 19 views
1

我正在查看一些遺留代碼。該類使用ArrayList來保存項目。這些項目是從數據庫表中提取的,可以達到600萬。該類公開了一個名爲「ListCount」的方法來獲取Arraylist中的項目數量。ArrayList計數與任何

Class Settings 
{ 
    ArrayList settingsList ; 
    public Settings() 
    { 
     settingsList = GetSettings();//Get the settings from the DB. Can also return null 
    } 

    public int ListCount 
    { 
     get 
     { 
      if (settingsList == null) 
      return 0; 
      else 
      return settingsList.Count; 
     } 
    } 
} 

ListCount用於檢查列表中是否有項目。我想知道給班上介紹'Any'的方法。

public bool Any(Func<vpSettings, bool> predicate) 
{ 
    return settingsList !=null && settingsList.Cast<vpSettings>().Any(predicate); 
} 

問題是框架是否進行某種優化並保持項目的計數或迭代Arraylist以獲得計數?如上所述添加「Any」方法是否可取?在以下問題

馬克碎石建議使用任何的IEnumerable的

Which method performs better: .Any() vs .Count() > 0?

+0

你可以顯示'GetSettings'嗎?至於這個例子,'IList'和'IDictionary'從'ICollection'派生。這是額外一層靈活性的好處之一。一個'數組'應該有更少的開銷並且更快。 – Greg

+0

@ Greg .. GetSettings()完成一堆事情,並調用其他類中的方法最終從數據庫讀取數據。老實說代碼遍佈這個方法的地方。 – AlwaysAProgrammer

回答

4

.NET reference source說ArrayList.Count返回一個緩存的私有變量。

爲了完整,the source也列出了Any()擴展方法的實現。基本上,擴展方法執行空檢查,然後嘗試通過IEnumerable的枚舉器獲取第一個元素。

+0

感謝您指向.Net參考源 – AlwaysAProgrammer

+3

Roslyn項目是我最喜歡的事情之一 - 如果您以前沒有見過,也可以將它與Visual Studio集成,以便您可以檢查/逐步通過代碼。獲得快速答案非常方便(或者找出結構)。這裏是[更多信息](http://blogs.msdn.com/b/dotnet/archive/2014/02/24/a-new-look-for-net-reference-source.aspx) –

+1

@Yogendra .NET參考資料本身並不是羅斯林項目的結果;它自2007年以來一直可用。然而,最近Roslyn的經驗得到了增強。另見http://visualstudiomagazine.com/articles/2014/02/26/dotnet-source-updated-via-roslyn.aspx。 – phoog

1

ArrayList實現IList所以它確實有Count財產。如果你所關心的是檢查容器(非)空虛,使用這將比Any()更快。

1

ArrayList實際上是實施IList,應該比.Any()更快。原因雖然是因爲它正在執行Count Property而不是Count MethodCount Property應該做一個快速檢查,然後抓住適當的屬性。

它看起來類似於:

ICollection<TSource> collection1 = source as ICollection<TSource>; 

    if (collection1 != null) 
    return collection1.Count; 

    ICollection collection2 = source as ICollection; 

    if (collection2 != null) 
    return collection2.Count; 
2

Marc Gravel建議使用Any()而不是Count()(擴展方法),但不一定要超過Count(屬性)。

Count屬性總是會更快,因爲它只是查找存儲在堆中的int。使用linq需要一個(相對)昂貴的對象分配來創建IEnumerator,再加上MoveNext中的任何開銷(如果列表不是空的,在返回true之前將不必要地將ArrayList的第一個成員的值複製到Current屬性中) 。

現在,這對於性能來說都是非常微不足道的,但是執行代碼的代碼更復雜,因此只有在具有令人信服的性能優勢時才能使用它。由於實際上存在一個微不足道的性能損失,我們應該選擇更簡單的代碼。因此,我會實施Any()作爲return Count > 0;

但是,您的示例正在實現Any的參數化重載。在這種情況下,您的解決方案委託給參數化的任何擴展方法似乎是最好的。參數化的Any擴展方法和Count屬性之間沒有關係。

+0

在我的示例中,arraylist已經填充。所以謂詞會做內存中的過濾。 – AlwaysAProgrammer

+0

@Yogendra我想我明白了。我有點困惑,因爲你的第一個例子涉及Count屬性,而第二個例子涉及過濾的Any方法。像你在你的例子中一樣實現這個功能的優點是封裝了Cast調用,支持DRY原則(http://en.wikipedia.org/wiki/Don't_repeat_yourself)。 – phoog