的Structs暴露字段是不是邪惡。雖然一些非常老的編譯器會接受類似的代碼:
List<Point> myList;
myList[4].X = 5;
這將複製myList中[4]爲臨時結構,修改臨時結構領域X,然後拋出修改後的結構遠,使得結構不變是一種確保編譯器能夠對上述構造進行攻擊的方法,確保編譯器在這些代碼中發聲的更好方法是將編譯器更改爲禁止寫入臨時結構的字段。由於這些代碼長時間被編譯器禁止,因此暴露域的結構通常是保存具有固定數量的獨立數據項(例如Point,Rectangle等)的東西的最佳方式。
什麼是問題是構造函數或屬性設定器以外的函數修改this
的結構。雖然編譯器會認識到寫入someStructProperty.someField
正在嘗試修改someStructProperty
,並且在這種修改實際上不起作用的情況下將禁止它,但不幸的是,編譯器不知道someStructProperty.MutatingFunction()
會嘗試修改臨時實例結構。因此編譯器會允許這樣的代碼,儘管它實際上不能按預期工作。如果函數應該修改一個結構「in place」,我會建議作爲一種補救措施,那就是定義一個靜態方法,它將結構的一個實例作爲參數ref
。例如,SetPointXY(ref Point pt, int x, int y)
。編譯器會將結構的傳遞視爲ref
參數作爲修改該結構的嘗試,並且只會在實際工作的情況下允許它。
請注意,從性能的角度來看,只有單獨編寫struct字段不會是更新結構的最快方法,那就是當大部分結構匹配默認值或其他預設值時,現有的結構。可能有一些情況下,用一個預先存在的實例覆蓋一個結構會更快,然後編寫應該包含不同內容的字段,但通常我會建議應該使用方法或函數來僅在更新結構時纔會更新結構這樣做的代碼比單獨設置字段的代碼更具可讀性。如果AreaCode
是PhoneNumber
類型的公共字段,則somePhoneNumber.AreaCode = "847";
的效果遠遠超過somePhoneNumber = new PhoneNumber("847", somePhoneNumber.Exchange, somePhoneNumber.Number, somePhoneNumber.Extension);
的效果。除其他外,必須研究整個結構以瞭解後者是否會改變AreaCode
以外的任何字段。另一方面,如果一個人的目標實際上是一個空白的結構,除了一些全新的數據,那麼使用構造函數或工廠方法可能有助於澄清這樣一個事實:如果單獨覆蓋結構的所有字段,則必須研究整個結構以知道沒有任何字段可以保持不變。
你的基準測試表明速度更快? – 2012-02-21 16:01:51
我不知道如何使用基準。無法一次學習所有內容。 – zgnilec 2012-02-21 16:02:59
您是否有理由相信它在您的應用程序中有所不同?這聽起來像是過早的優化。 – 2012-02-21 16:04:09