屬性 讓開發者在程式碼中嵌入宣告式中繼資料,編譯進組件,執行期透過反射讀取。廣泛用於序列化、驗證、條件編譯、框架擴展點等場景。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AuthorAttribute : Attribute {
public string Name { get; }
public string Email { get; set; } // 可選位置參數/命名參數
public AuthorAttribute(string name) => Name = name;
}
// 使用
[Author("Ben Albahari", Email = "ben@example.com")]
public class MyClass {
[Obsolete("Use NewMethod()", true)] // 編譯器警告/錯誤
public void OldMethod() { }
[Conditional("DEBUG")] // 僅 DEBUG 編譯時保留呼叫
public void DebugLog(string msg) { }
}
| 屬性 | 用途 | 目標 |
|---|---|---|
Obsolete | 標記過時 API,編譯器警告/錯誤 | 所有 |
Conditional | 條件編譯方法呼叫 | 方法 |
Serializable | 標記可序列化類別 | 類別/結構 |
AttributeUsage | 限制屬性適用目標、可重複性、繼承性 | 屬性類別 |
CallerMemberName | 自動填入呼叫端成員名稱 | 參數 |
CallerFilePath | 自動填入呼叫端檔案路徑 | 參數 |
CallerLineNumber | 自動填入呼叫端行號 | 參數 |
var attrs = typeof(MyClass).GetCustomAttributes(inherit: true);
foreach (var attr in attrs) {
Console.WriteLine($"Author: {attr.Name}, Email: {attr.Email}");
}
// 方法屬性
var method = typeof(MyClass).GetMethod("OldMethod");
var obsolete = method.GetCustomAttribute();
if (obsolete != null) Console.WriteLine($"Obsolete: {obsolete.Message}");
public class User {
[Required]
[StringLength(50, MinimumLength = 2)]
public string Name { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Range(18, 120)]
public int Age { get; set; }
}
// 驗證
var context = new ValidationContext(user);
var results = new List();
bool valid = Validator.TryValidateObject(user, context, results, true);
public class Person {
[JsonPropertyName("full_name")]
[XmlElement("Name")]
public string Name { get; set; }
[JsonIgnore]
[XmlIgnore]
public string InternalId { get; set; }
[JsonConverter(typeof(UnixTimestampConverter))]
public DateTime BirthDate { get; set; }
}
[ServiceLifetime(ServiceLifetime.Scoped)]
public interface IUserService { }
[AttributeUsage(AttributeTargets.Class)]
public class ServiceLifetimeAttribute : Attribute {
public ServiceLifetime Lifetime { get; }
public ServiceLifetimeAttribute(ServiceLifetime lifetime) => Lifetime = lifetime;
}
[TestClass]
public class CalculatorTests {
[TestMethod]
[DataRow(1, 2, 3)]
[DataRow(-1, 1, 0)]
public void Add_Test(int a, int b, int expected) {
Assert.AreEqual(expected, a + b);
}
[TestMethod]
[ExpectedException(typeof(DivideByZeroException))]
public void DivideByZero_Test() { 1 / 0; }
}
System.AttributeAttributeUsage 限制目標sealed (除非設計為基底)| 特性 | C# Attribute | Java Annotation |
|---|---|---|
| 語法 | [Attribute] | @Annotation |
| 編譯輸出 | 編譯進 IL 中繼資料 | 可選擇 SOURCE/CLASS/RUNTIME 保留策略 |
| 參數類型 | 基本型別、Type、enum、陣列 | 類似,支援預設值 |
| 繼承 | AttributeUsage(Inherited=true) | @Inherited |
| 條件編譯 | ConditionalAttribute | 無直接對應 |
屬性是 C# 宣告式程式設計的核心機制,將中繼資料從程式邏輯分離,編譯期嵌入、執行期反射讀取。善用預定義屬性 (Obsolete, Conditional, DataAnnotations) 並設計自訂屬性,能構建極具擴展性的框架與工具。