創建對像是否昂貴?
我剛剛重構了一位同事的程式碼,大致看起來像這樣……
public class Utility public void AddHistoryEntry(int userID, HistoryType Historytype, int companyID) { // Do something... } public void AddHistoryEntry(int userID, HistoryType historyType, int companyID, string notes) { // Do something... } }對此…
public class HistoryEntry { public long UserID { get; private set; } public HistoryType HistoryType { get; private set; } public long CompanyID { get; set; } public string Notes { get; set; } public HistoryEntry(long userID, HistoryType historyType) { this.UserID = userID; this.HistoryType = historyType; } } public class Utility { public void AddHistoryEntry(HistoryEntry entry) { // Do something... } }現在,這是更好的程式碼設計,是 Bob 大叔的最愛。但是,我的同事認為,每次我們想要呼叫此方法時,都需要更新一個對象的成本要高得多。
他是對的嗎?
進一步說明
- 實用程序類不存在。我只是想將這些方法放在一個類中供大家查看。實際上,它屬於一個明智的類。
- 事實上,原始程式碼中有 5 個 AddHistoryEntry 方法。所有這些都需要很多 int 參數。重構的一個原因是它
AddHistory(0, 1, 45, 3);並沒有真正告訴你太多!- AddHistoryEntry 不是從緊密循環中呼叫的,但它在整個應用程序中被廣泛使用。
更正
我現在更新了程式碼範例,因為我在某些參數上犯了錯誤。
如果您同時在記憶體中擁有數百萬個這樣的對象,他可能是正確的。但如果你不這樣做,那麼他提出的幾乎可以肯定是一個有爭議的問題。始終首先選擇更好的設計,然後僅在不滿足性能要求時對其進行修改。
創建一個新對象非常便宜。您必須在一個非常緊湊的循環中創建很多對象才能注意到任何差異……但同時,它不是免費的。您還需要記住,成本是半隱藏的——當您創建對象時,您需要預先支付一些成本,但這也意味著垃圾收集器還有更多工作要做。
那麼更清潔的設計是否值得性能打擊?我們不能告訴你——這取決於你的程式碼是如何使用的。我強烈懷疑對性能的影響將是微不足道的,但如果你在一個緊密的循環中使用它,它可能不會。但是,只有一種方法可以找出答案:如果您擔心,請測量它。就我個人而言,我可能會選擇更簡潔的設計,並且只有在看起來成為問題時才檢查性能。
(如果這種方法是命中磁碟或數據庫,順便說一句,差異幾乎肯定是微不足道的。)
順便提一個建議:你的
HistoryEntry類型真的需要可變嗎?您能否將所有屬性設置為只讀,並由私有隻讀變數支持?只是提到威爾的觀點——我有點同意他的觀點。如果這兩種方法是您需要這個概念的唯一地方,我完全不確定是否值得為此創建一個新類型。不是因為性能方面,而是因為您引入了一堆額外的程式碼而沒有顯示出任何好處。這裡的關鍵詞是展示 - 如果您實際上在其他地方使用相同的參數集合,或者可以有效地將邏輯放入
HistoryEntry類中,那完全是另一回事。編輯:只是為了回應關於多個整數參數的觀點 - C# 4 將允許命名參數,這應該會使這更容易。所以你可以打電話:
AddHistoryEntry(userId: 1, companyId: 10);使用附加類使名稱可見需要以下之一:
- 來自 C# 4 的命名建構子參數(在這種情況下,你並不比使用該方法更好)
- 可變類型(呃——這可能導致難以追踪原始版本中沒有的錯誤)
- 用於構造實例(“FromUserAndCompanyId”)的長靜態方法名稱,隨著參數的增加變得笨拙
- 可變的建構器類型
- 一堆“With”方法:
new HistoryEntry().WithCompanyId(...).WithUserId(...)- 這使得在編譯時驗證您是否提供了所有必需的值變得更加困難。