寫程式一段時間後,我和同事突然開始討論起「屬性 (Property)」和「欄位 (Field)」之間的區別
這兩者經常用來定義資料實體模型或 API 的 Model,但具體有何不同?
這個話題看似簡單,實際上卻值得深究
了解它們的差異,能讓我們在開發過程中更好地使用這些關鍵概念,進而提升程式的可維護性和效能
欄位(Field)
修飾詞:通常為 private
使用時機:
- 適用於值需要自我驗證的型別,如 Boolean,只允許
True
或False
- 資料型別範圍內的任何值都是有效的,適合於
Single
或Double
型別 - 對於
String
型別的屬性,無限制的字串長度或值
屬性(Property)
修飾詞:通常為 public
使用時機:
- 需要控制何時及如何設定或取得值
- 需要定義並驗證的值集合
- 設定值時會改變物件狀態,如
IsVisible
- 設定值影響內部變數或其他屬性
- 設定或取得前需要執行一組步驟
using System; namespace Demo.Model { public class UserInfo { #region 欄位(Field) private long _userID; private string _userName; #endregion #region 屬性(Property) /// <summary> /// 用戶ID /// </summary> public long UserID { get { return _userID; } set { _userID = value; } } /// <summary> /// 用戶名稱 /// </summary> public string UserName { get { return _userName; } set { _userName = value; } } #endregion } }
C# 3.0 自動屬性實作 (Auto-Implemented Properties)
- 當屬性存取子中不需要額外的邏輯時
- 自動實作的屬性可讓屬性宣告變得更精簡它們還可讓用戶端程式碼建立物件
- 當您宣告屬性時,如下列範例所示,編譯器會建立私用、匿名的支援欄位
- 但只能透過屬性的 get 和 set 存取子才能存取
using System; namespace Demo.Model { public class UserInfo { /// <summary> /// 用戶ID /// </summary> public long UserID { get; set; } /// <summary> /// 用戶名稱 /// </summary> public string UserName { get; set; } } }
C# 6 自動實作的屬性
可以初始化自動實作的屬性,就像欄位一樣
using System; namespace Demo.Model { public class UserInfo { /// <summary> /// 用戶ID /// </summary> public long UserID { get; set; } = 123; /// <summary> /// 用戶名稱 /// </summary> public string UserName { get; set; } = "Bill"; } }
限制存取子的存取範圍
- 可將 set 存取子宣告為 private
- 屬性只有在類型內才可設定,但是它對於使用者而言是不可變的
- 當您宣告私用 set 存取子時,則無法使用物件初始設定式來初始化屬性。 您必須使用建構函式或 Factory 方法
- 您可以只宣告 get 存取子,使屬性在任何地方都不可變,除了型別的函式之外
using System; namespace Demo.Model { public class UserInfo { /// <summary> /// 用戶ID /// </summary> public long UserID { get; private set; } /// <summary> /// 用戶名稱 /// </summary> public string UserName { get; set; } = "Bill"; } }
參考文獻
https://docs.microsoft.com/zh-tw/dotnet/csharp/programming-guide/classes-and-structs/how-to-implement-a-lightweight-class-with-auto-implemented-properties