特性是C#中用于向程序元素(类、方法、字段等)附加元数据的机制,本质是继承自System.Attribute
的类。它们像“魔法斗篷”一样,为代码元素添加额外信息,这些信息可在编译期或运行时被读取和利用。
[Obsolete]
标记废弃代码,[DllImport]
调用本地库。// 自定义特性类,必须继承System.Attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, // 可应用的目标
AllowMultiple = true, // 是否允许多次应用
Inherited = false)] // 是否可继承
public sealed class MyCustomAttribute : Attribute
{
// 位置参数(必须通过构造函数定义)
public string Description { get; }
// 命名参数(通过公共属性/字段定义)
public int Priority { get; set; }
// 构造函数定义位置参数
public MyCustomAttribute(string description)
{
Description = description;
}
}
// 应用自定义特性到类
[MyCustom("这是一个魔法类", Priority = 1)]
public class MagicClass
{
// 应用特性到方法
[MyCustom("魔法方法", Priority = 2)]
public void CastSpell()
{
// ...
}
}
// 位置参数必须放在首位,且顺序不可变
[MyCustom("描述", Priority = 10)] // 合法
[MyCustom(Priority = 10, "描述")] // 报错:位置参数必须先出现
// 允许多次应用特性(需设置AllowMultiple = true)
[MyCustom("第一次"), MyCustom("第二次")]
public class MultiMagicClass
{
// 可通过反射获取所有实例
}
[Obsolete]
// 标记方法为废弃,并指定错误级别
[Obsolete("请使用NewMethod替代", true)] // true表示编译报错
public void OldMethod()
{
// ...
}
[Conditional]
// 条件编译:仅在定义DEBUG时调用
[Conditional("DEBUG")]
public void DebugLog(string message)
{
Console.WriteLine($"DEBUG: {message}");
}
// 调用时,非DEBUG模式下代码会被忽略
public void Test()
{
DebugLog("仅在调试时显示"); // 非DEBUG模式下不执行
}
[DllImport]
// 调用本地DLL函数
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
// 获取类上的特性
var type = typeof(MagicClass);
var attributes = type.GetCustomAttributes<MyCustomAttribute>();
foreach (var attr in attributes)
{
Console.WriteLine($"描述: {attr.Description}, 优先级: {attr.Priority}");
}
// 获取方法上的特性
var method = type.GetMethod("CastSpell");
var methodAttr = method.GetCustomAttribute<MyCustomAttribute>();
Console.WriteLine($"方法优先级: {methodAttr.Priority}");
// 定义权限特性
[AttributeUsage(AttributeTargets.Method)]
public class PermissionAttribute : Attribute
{
public string Role { get; }
public PermissionAttribute(string role)
{
Role = role;
}
}
// 应用特性到方法
public class SecureService
{
[Permission("Admin")]
public void DeleteData()
{
// ...
}
}
public class PermissionInterceptor
{
public void ExecuteMethod(object instance, MethodInfo method)
{
// 获取方法上的权限特性
var attr = method.GetCustomAttribute<PermissionAttribute>();
if (attr != null)
{
// 检查用户权限(模拟)
if (!IsUserInRole(attr.Role))
{
throw new UnauthorizedAccessException();
}
}
// 执行方法
method.Invoke(instance, null);
}
private bool IsUserInRole(string role)
{
// 实际实现:从用户会话获取角色
return role == "Admin";
}
}
// 定义日志特性
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute
{
public string LoggerName { get; }
public LogAttribute(string loggerName)
{
LoggerName = loggerName;
}
}
// 应用特性到方法
public class Service
{
[Log("PerformanceLogger")]
public void ProcessData()
{
// ...
}
}
// 切面拦截器
public class AspectWeaver
{
public void ExecuteWithLogging(object instance, MethodInfo method)
{
var attr = method.GetCustomAttribute<LogAttribute>();
if (attr != null)
{
Console.WriteLine($"[LOG] {attr.LoggerName} 开始执行 {method.Name}");
}
// 执行方法
method.Invoke(instance, null);
if (attr != null)
{
Console.WriteLine($"[LOG] {method.Name} 执行完成");
}
}
}
// 错误:字段名与'field'关键字冲突(C#14新特性)
public class ConflictingClass
{
private string field; // ❌ 与C#14的隐式字段冲突
// 解决方案:使用@转义或重命名
private string @field; // ✅
}
// 避免在高频方法中使用反射获取特性
// 优化方案:缓存特性信息
public class AttributeCache
{
private static readonly Dictionary<Type, List<Attribute>> _cache = new();
public static List<Attribute> GetCachedAttributes(Type type)
{
if (!_cache.TryGetValue(type, out var attrs))
{
attrs = type.GetCustomAttributes().ToList();
_cache[type] = attrs;
}
return attrs;
}
}
// 新特性:直接引用隐式字段
public class SimpleName
{
// 简化属性定义
public string Name
{
get => field;
set => field = value.Trim(); // 自动处理空格
}
}
// 对比传统写法:无需显式声明字段
// private string _name;
// public string Name { get => _name; set => _name = value; }
[AttributeUsage(AttributeTargets.Property)]
public class ConfigAttribute : Attribute
{
public string Key { get; }
public ConfigAttribute(string key)
{
Key = key;
}
}
public class AppConfig
{
[Config("timeout")]
public int Timeout { get; set; }
[Config("maxRetries")]
public int MaxRetries { get; set; }
}
public class ConfigLoader
{
public void LoadConfig(AppConfig config, Dictionary<string, string> source)
{
foreach (var prop in typeof(AppConfig).GetProperties())
{
var attr = prop.GetCustomAttribute<ConfigAttribute>();
if (attr != null && source.TryGetValue(attr.Key, out var value))
{
prop.SetValue(config, Convert.ChangeType(value, prop.PropertyType));
}
}
}
}
通过本文的深度实践,开发者可以掌握:
[Obsolete]
、[Conditional]
等实战field
关键字简化属性管理