程式寫一段時間,突然跟同事探討屬性(Property)與欄位(Field)差在哪裡?
大多用法都是拿來定義資料實體模型或是API的Model
欄位(Field)
通常修飾詞為private,使用時機
- 值屬於自我驗證型別。例如,如果將 True 或 False 以外的值指派給 Boolean 變數,會發生錯誤或自動資料轉換
- 資料型別所支援範圍內的任何值為有效值。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