<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 原則26:避免返回類的內部對象的引用 **By D.S.Qiu** **尊重他人的勞動,支持原創,轉載請注明出處:[http://dsqiu.iteye.com](http://dsqiu.iteye.com)** 你可能會覺得只讀屬性是只讀的所以調用者不能修改它。不幸的是,這并不總是奏效的方法。如果你的屬性返回引用類型,調用者可以訪問任何 public 的對象成員,包括那些能修改屬性狀態。例如: ``` public class MyBusinessObject { // Read Only property providing access to a // private data member: private BindingList<ImportantData> listOfData = new BindingList<ImportantData>(); public BindingList<ImportantData> Data { get { return listOfData; } } // other details elided } // Access the collection: BindingList<ImportantData> stuff = bizObj.Data; // Not intended, but allowed: stuff.Clear(); // Deletes all data. ``` MyBusinessObject 的任何使用者都可以修改你的內部數據集。你可以創建屬性隱藏內部數據結構。你提供方法允許客戶端只能通過這些方法操作數據,因此你可以管理內部狀態的改變。只讀屬性打開類封裝的后門。當你考慮這類問題時,你會認為它不是一個可讀寫的屬性,而是一個只讀屬性。 歡迎來到一個基于引用的精彩系統。任何返回引用的成員都會返回對象的句柄。你給了調用者你的內部結構的句柄,因此調用者不再需要通過對象修改包含的引用。 顯然,你需要阻止這類行為。你構建接口,并且希望使用者使用它。你不希望使用者可以在你不知情的情況下改變對象的內部狀態。你有四種策略包含你的內部數據結構不被任意修改:值類型,不可變類型,接口和包裝器。 值類型會被復制當客戶端通過屬性訪問它們。客服端對復雜的類數據的任何改變,都不會影響你對象內部狀態。客戶端可以根據需求隨意的改變復雜的數據。這不會影響你的內部狀態。 不可變類型,例如 System.String 同樣是安全的(查看原則20)。你返回 string ,或者其他不可變類型,很安全地知道沒有客戶端可以改變字符串。你的內部狀態是安全的。 第三種方案是定義接口,從而允許客服端訪問內部成員的部分功能(查看原則22)。當你創建一個自己的類時,你可以創建一些接口,用來支持對類的部分的功能。通過這些接口來暴露一些功能函數,你可以盡可能的減少一些對數據的無意修改。客戶可以通過你提供的接口訪問類的內部對象,而這個接口并不包含這個類的全部的功能。在 List&lt;T&gt; 中暴露 IEnumerable&lt;T&gt; 接口就是這個策略的例子。聰明的程序可以阻止那些猜測實現接口的對象實際類型并使用強制類型轉換。但是那些那樣做的程序員就是花更多時間去創建 bug ,這是他們應得的。 這個在 BindingList 類會有點小麻煩會引起一些問題。因為沒有泛型版本的 IBindingList ,所以你需要創建兩個不同的 API 方法訪問數據:一個通過 IBindingList 接口支持 DataBinding ,一個通過 ICollection&lt;T&gt; 或其他類似接口編程支持。 ``` public class MyBusinessObject { // Read Only property providing access to a // private data member: private BindingList<ImportantData> listOfData = new BindingList<ImportantData>(); public IBindingList BindingData { get { return listOfData; } } public ICollection<ImportantData> CollectionOfData { get { return listOfData; } } // other details elided } ``` 在我們開始討論如何創建一個完全只讀的數據視圖時以前,讓我先簡單的了解一下你應該如何響應客服端的修改。這是很重要的,因為你可能經常要暴露一個 IBindingList 給 UI 控件,這樣用戶就可以編輯數據。毫無疑問你已經使用過 Windows 表單的數據綁定,用來給用戶提供對象私有數據編輯。BindingList&lt;T&gt; 類實現 IBindingList 接口,所以你響應展示給用戶的集合的任何添加,更新,或者刪除元素的操作。 任何時候,當你期望給客戶端提供修改內部數據的方法時,都可以擴展這個的技術,但你要驗證而且響應這些改變。你的類訂閱對內部數據結構產生改變的事件。事件處理器驗證改變或者響應這些改變以更新其他內部狀態。 回到開頭的問題上,你想讓客戶查看你的數據,但不許做任何的修改。當你的數據存儲在一個 BindingList&lt;T&gt; 里時, 你可以通過強制在 BindingList 上設置一些屬性( AddEdit , AllowNew ,AllowRemove等)。這些屬性的值被 UI 控件控制。UI 控件基于這些屬性值開啟和關閉不同的行為。這些是 public 的屬性,所以你可以修改集合的行為。但是那樣也還沒有作為 public 屬性暴露 BindingList&lt;T&gt; 對象。客戶端可以修改你的屬性并且規避使用只讀綁定集合的意圖。再強調一次,通過接口類型而不是類類型暴露內部存儲可以限制客服端代碼在這個對象上的行為。 最后一個選擇是提供一個包裝器對象并且值暴露這個包裝器實例,這可以減少訪問內部對象。 System.Collections.ObjectModel.ReadOnlyCollection&lt;T&gt; 類就是包裝集合并暴露一個只讀版本的數據的標準方法: ``` public class MyBusinessObject { // Read Only property providing access to a // private data member: private BindingList<ImportantData> listOfData = new BindingList<ImportantData>(); public IBindingList BindingData { get { return listOfData; } } public ReadOnlyCollection<ImportantData>CollectionOfData { get { return new ReadOnlyCollection<ImportantData>(listOfData); } } // other details elided } ``` 通過 public 接口直接暴露引用類型將允許使用者修改對象的內部而不通過你定義的方法或屬性。這看起來不可思議,確實一個常見的錯誤。你應該考慮到你暴露的是引用而不是值,因此需要修改類的接口。如果你只是簡單的返回內部數據,那么你就給了訪問它們包含的常用的權限。客戶端可以調用可訪問的方法。你要限制訪問private 內部數據要通過接口,包裝器對象或值類型。 小結: 這里說的確實是引用類型系統或者很多需要統一管理模型的一個通病,怎么才能做到對引用類型內部改變“一夫當關萬夫莫開”的效果,目前比較好的方法是使用接口! 歡迎各種不爽,各種噴,寫這個純屬個人愛好,秉持”分享“之德! 有關本書的其他章節翻譯請[點擊查看](/category/297763),轉載請注明出處,尊重原創! 如果您對D.S.Qiu有任何建議或意見可以在文章后面評論,或者發郵件(gd.s.qiu@gmail.com)交流,您的鼓勵和支持是我前進的動力,希望能有更多更好的分享。 轉載請在**文首**注明出處:[http://dsqiu.iteye.com/blog/2086266](/blog/2086266) 更多精彩請關注D.S.Qiu的博客和微博(ID:靜水逐風)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看