首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

Effective C# 原則 28:避免轉換運算子,防止隱性副作用與封裝破壞

     編輯:關於C#

轉換運算子:看似便利、實則危險

C# 允許定義隱性/顯性轉換運算子,宣告型別可替換性。但這往往引發難以發現的 Bug:

  • 轉換產生暫時物件,呼叫端修改的是暫時物件,原物件不變,修改隨 GC 消失。
  • 破壞封裝:透過轉換存取內部欄位,繞過類別定義的介面。
  • 基於編譯時期型別而非執行時期型別運作,行為難以預期。

經典反例:Circle 隱性轉換為 Ellipse

public class Circle : Shape {
    static public implicit operator Ellipse(Circle c) 
        => new Ellipse(c._center, c._center, c._radius, c._radius);
}

呼叫 Flatten(Ellipse e) 並傳入 Circle 時:

  1. 編譯器隱性產生新的 Ellipse 物件。
  2. Flatten 修改此暫時物件。
  3. 原 Circle 物件完全未被修改,暫時物件隨即成為垃圾。

改為顯性轉換 (Ellipse)c 同樣產生暫時物件,問題依舊。

正確替代方案:建構函式明確建立新物件

// 明確建立新 Ellipse,語意清晰,呼叫端知曉產生新物件
Flatten(new Ellipse(c));

進一步追蹤變數更佳:

Ellipse e = new Ellipse(c);
Flatten(e); // 保留修改後的 e

封裝破壞風險

回傳內部欄位的轉換運算子,等於公開內部實作細節,違反封裝原則(參見原則 23)。

總結

轉換運算子提供型別替換假象,實則引入暫時物件副作用、封裝洩漏、難以除錯的行為。應盡量避免使用,改用建構函式或工廠方法明確表達物件建立意圖。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved