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

C# 封裝箴言(三):屬性回傳參考型別的防禦性複製與驗證

     編輯:關於C語言

問題:屬性直接回傳私有參考型別會導致封裝破裂

public class Class1
{
    public string Data { get; set; }
}

public class Class2
{
    private Class1 _myClass1 = new Class1("init");
    public Class1 Class1 => _myClass1; // 直接暴露內部物件參考
}

// 使用端
var c2 = new Class2();
var c1 = c2.Class1;      // 取得內部物件參考
c1.Data = "tampered";    // 竄改 Class2 內部狀態,Class2 完全不知情!

解決方案:防禦性複製

  1. 讓內部類別實作 ICloneable(或自訂 Clone/Copy 方法)。
  2. 屬性 get 回傳副本而非原始參考。
public class Class1 : ICloneable
{
    private string _data;
    public Class1(string data) => _data = data;
    public string Data { get => _data; set => _data = value; }

    public object Clone() => new Class1(_data); // 深層複製(此處 string 為不可變,淺層即可)
}

public class Class2
{
    private Class1 _myClass1;
    public Class1 Class1 => _myClass1.Clone() as Class1; // 回傳副本

    public string Data => _myClass1.Data; // 唯讀暴露單一值

    public Class2(string data) => _myClass1 = new Class1(data);
}

現在外部修改回傳的 Class1 副本不會影響 Class2 內部狀態。

第二道防線:屬性 set 驗證

屬性是外部修改內部狀態的唯一入口,**必須在 set 進行有效性檢查**:

private int _age;
public int Age
{
    get => _age;
    set
    {
        if (value < 0 || value > 150)
            throw new ArgumentOutOfRangeException(nameof(value), "年齡需在 0~150 之間");
        _age = value;
    }
}

即使屬性為 private/protected,內部方法也應走屬性設值,保證驗證邏輯不被繞過。

WinForm 兩視窗資料傳遞的正確姿勢

網路上常見「將 Form1 設為 public static」或「傳遞 this 給 Form2」的錯誤做法。正確做法:

  • Form2 定義事件或委派,Form1 訂閱。
  • 或 Form2 暴露唯讀屬性,Form1 在 ShowDialog() 返回後讀取。
  • 核心原則:**資料擁有者負責驗證與封裝,使用者只能透過定義良好的介面存取。**
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved