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

C# 屬性與欄位深度解析:從常規屬性到自動實作屬性的選擇指南

     編輯:關於C#

前言:實體類別設計的核心抉擇

在 C# 開發中,實體類別幾乎無處不在。定義資料成員時,我們面臨三種選擇:常規屬性、自動實作屬性、欄位。本文將深入剖析三者的差異、適用場景與最佳實踐,助你做出正確的架構決策。

一、常規屬性:功能最完整、彈性最大

結構拆解

一個完整的常規屬性包含三個部分:

  1. 私有後備欄位:儲存實際資料,以 private 封裝,強制透過屬性存取。
    private string _name;
  2. get 存取子:負責讀取資料,可包含驗證、計算等邏輯,以 return 或 throw 結束。
    get
    {
        // 價格不可為負,異常時回傳 0
        return _price >= 0 ? _price : 0;
    }
    原則:get 不應修改物件狀態(如回傳時附加字串屬不佳實踐)。
  3. set 存取子:負責寫入資料,類似 void 方法,可包含邏輯處理(如預設值計算)。
    set
    {
        _name = value?.Trim() ?? string.Empty;
    }

分類維度

維度說明
存取修飾詞public、private、protected、internal、protected internal、private protected
靜態性靜態屬性、實例屬性(靜態屬性不可與 virtual/abstract/override 混用)
虛擬/抽象虛屬性、抽象屬性、覆寫屬性
讀寫性唯讀、唯寫、可讀可寫

二、自動實作屬性:語法糖,簡潔但有限制

當存取子不需要額外邏輯時,可使用自動實作屬性:

public string Name { get; set; }

編譯器會自動產生私有匿名後備欄位,僅能透過屬性存取。

關鍵限制

  1. 必須同時宣告 get 與 set:若需唯讀,請用 private set。
  2. 不允許在後備欄位加上 Attribute:需改用常規屬性。
  3. 存取子內無法撰寫邏輯:功能上類似欄位,但保留屬性的封裝優勢(可日後擴充邏輯不破壞介面)。

三、欄位:最輕量但封裝最弱

核心差異

特性欄位屬性
資料驗證無法攔截賦值(如身高設 1000m)可在 set 中攔截驗證
ref/out 傳遞支援不支援(屬性非變數分類)
序列化/繫結部分需特殊處理標準支援
介面定義不可用於介面可定義於介面

錯誤示範:屬性不可作 ref/out 參數

class Student { public string Name { get; set; } }

void RefMethod(ref string name) { name += "ref"; }
void OutMethod(string name, out string name2) { name2 = name + "out"; }

var s = new Student { Name = "王五" };
RefMethod(ref s.Name); // 編譯錯誤 CS0206
OutMethod(s.Name, out var n); // 編譯錯誤 CS0206

四、三者選擇決策樹

  1. 需要邏輯驗證、計算、延遲載入、事件通知 → 常規屬性。
  2. 單純資料儲存,當前無邏輯,但未來可能擴充 → 自動實作屬性(預設首選)。
  3. 極簡 DTO、內部暫存、效能極度敏感、需 ref/out → 欄位(建議 private 配合方法封裝)。

五、實戰案例:反射複製屬性值

常規屬性支援反射列舉,適合物件間屬性批次複製:

PropertyInfo[] srcProps = src.GetType().GetProperties();
PropertyInfo[] dstProps = dst.GetType().GetProperties();

foreach (var sp in srcProps)
{
    if (!sp.CanRead) continue;
    var dp = dstProps.FirstOrDefault(p =>
        p.Name.Equals(sp.Name, StringComparison.OrdinalIgnoreCase) &&
        p.PropertyType == sp.PropertyType &&
        p.CanWrite);
    if (dp != null)
        dp.SetValue(dst, sp.GetValue(src));
}

此技巧廣泛用於 DTO 轉換、領域模型映射等場景。

總結

屬性是封裝的第一道防線。自動實作屬性兼顧簡潔與擴充性,是現代 C# 開發的預設選擇;常規屬性處理複雜業務規則;欄位僅限內部實作細節。善用三者,寫出健壯且可維護的程式碼。

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