“優秀的程序員的標準之一是:編寫更易于擴展的代碼”
@圖片:奧森公園的向日葵 拍攝于2022年7月23日
01
—
問題緣起
上一篇中,我們知道List<T>的是基于數組實現的可變長度的列表。
很多小伙伴發現,List<T>即有Count屬性又有Count()方法,并且有人做過性能測試,Count屬性比Count()方法更快,因此得出結論,Count屬性是直接返回一個計算好的值,Count()方法需要遍歷列表計算長度。
事實是怎樣的?像微軟這樣全球頂級的開發團隊,是否會在基礎類庫中提供兩個一樣的功能,我們來探究一下。
02
—
源碼探究
Count屬性是List<T>提供的只讀屬性,直接返回私有變量_size記錄的元素數量。
Count()方法是System.Linq.Enumerable中提供的擴展方法,List<T>實現接口IList<T>,間接實現接口ICollection<T>,由源碼可知,通過List<T>對象調用Count()方法,返回的是List<T>對象的Count屬性,二者并沒有區別。
Count()方法存在的意義是什么呢?
03
—
軟件設計原則
微軟設計原則,參數設計原則中有一條:
請使用提供成員所需功能的最低派生參數類型。?
例如,假設你想要設計這樣一種方法,它可枚舉集合并將每個項目輸出到控制臺。?此類方法應將 IEnumerable 用作參數,而不是使用 ArrayList 或 IList 等內容。
微軟文檔:https://learn.microsoft.com/zh-cn/dotnet/standard/design-guidelines/parameter-design
微軟設計原則建議,在滿足所需功能的情況下,應使用IEnumerable,而不是使用ArrayList或IList,這也叫說明了Count()方法存在的意義,因為在IEnumerable中沒有Count屬性,只能通過Count()方法間接獲取元素數量。
這里體現了面向對象開發原則(SOLID),使用最低派生類型,職責單一,其子類型(實現類)易于替換,代碼可擴展性更好,符合開放封閉原則。
如何看待Count()方法比Count屬性慢?
04
—
正確認識性能問題
客觀的看待性能問題,應當從相對性能和絕對性能兩方面進行交叉對比,從而得出一個中肯的結論。
Count()方法比Count屬性,大概慢10ns(不同設備環境會有差異),也就是百萬分之十毫秒,一億分之一秒,絕對性能差異微乎其微,而大部分性能測試為了體現兩者的性能差異,循環上百萬次,再對兩者進行對比,通過相對性能展示性能差異,殊不知,Count屬性本身耗時極低,相對性能差異被夸大。
這一點一定要認識清楚,同樣的有文章分析在List<T>集合中Exists()比Any()性能好,也是相同的原理,切不可被片面的言論左右。
軟件開發過程就是一個決策取舍的過程,你是希望獲得更高的性能,還是更好的擴展性,相信每個小伙伴心中都有自己的答案。
喜歡的朋友可以點贊,轉發,加關注