屬性是 C# 最具生產力的特性之一,將「存取器/設定器」模式內建於語言層級,提供比 Java/C++ 更直觀、安全、可維護的資料封裝方式。
| 語言 | 定義 | 使用 |
|---|---|---|
| Java/C++ | | foo.setSize(foo.getSize() + 1); |
| C# | | foo.Size++; |
getX()/setX() 命名慣例不一致問題
private string _name;
public string Name {
get => _name ?? "Unknown";
set {
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Name cannot be empty");
_name = value.Trim();
}
}
///)
public string PublicProp { get; set; }
public string ReadOnlyProp { get; private set; }
public string WriteOnlyProp { private get; set; } // 罕用
internal string InternalSetProp { get; internal set; }
protected string ProtectedProp { get; protected set; }
// 編譯器自動產生隱藏支援欄位
public int Age { get; set; }
public string Name { get; } = "Default"; // 唯讀自動屬性 (C# 6.0+)
public Guid Id { get; } = Guid.NewGuid(); // 初始化運算式
public class Person {
public string Name { get; }
public DateTime BirthDate { get; }
public Person(string name, DateTime birthDate) {
Name = name;
BirthDate = birthDate;
}
}
public double Area => Math.PI * Radius * Radius;
public string FullName => $"{FirstName} {LastName}";
public class ViewModel : INotifyPropertyChanged {
private string _title;
public string Title {
get => _title;
set {
if (_title != value) {
_title = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Title)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
private Lazy _resource = new(() => new ExpensiveResource());
public ExpensiveResource Resource => _resource.Value;
public class Matrix {
private double[,] _data;
public double this[int row, int col] {
get => _data[row, col];
set => _data[row, col] = value;
}
}
| 誤區 | 正確做法 |
|---|---|
| 屬性執行複雜/耗時運算 | 屬性應快速完成;複雜運算改用方法 (如 Calculate()) |
| 屬性回傳可變集合內部參考 | 回傳唯讀視圖或複本 (AsReadOnly(), ToArray()) |
過度使用 set 導致不可預期副作用 | 考慮不可變設計,僅在建構子初始化 |
忽略 value 參數驗證 | 永遠驗證輸入,拋出具體例外 (ArgumentException) |
private int _age;)C# 屬性系統將封裝模式語言化,提供語法糖、編譯器保證、工具支援三重保障。善用自動屬性、唯讀屬性、運算式主體、存取層級控制,能寫出更清晰、安全、可維護的程式碼。這是 C# 區別於 Java/C++ 的關鍵生產力特性之一。