C# 特性(Attributes)详解

C# 特性(Attributes)详解

什么是特性?

特性(Attributes) 是 C# 提供的一种强大的元数据机制,用于在代码中添加描述性信息。它可以附加到程序的各种部分(类、方法、属性、字段等),供运行时或编译时使用。


常见用途

  1. 标注元数据
    • 为代码元素提供额外的信息。
    • 例如 [Obsolete] 特性提示某个方法已过时。
  1. 控制行为
    • 特性可以影响代码的执行逻辑或框架的行为。
    • 例如 [HttpGet] 告知 ASP.NET Core 这是一个 GET 请求的处理方法。
  1. 运行时反射
    • 通过反射获取特性的信息,动态改变程序逻辑。
    • 例如,通过 [Authorize] 特性决定用户是否有权限访问某功能。
  1. 编译器指令
    • 提供编译时的额外指令或警告信息。
    • 例如 [Conditional] 特性控制代码的条件编译。

如何定义和使用特性?

1. 内置特性

示例 1:[Obsolete]

标记某个方法或类为"已过时"。

复制代码
csharp


复制代码
public class Example
{
    [Obsolete("Use NewMethod instead.")]
    public void OldMethod()
    {
        Console.WriteLine("This is an old method.");
    }

    public void NewMethod()
    {
        Console.WriteLine("This is a new method.");
    }
}

使用时会提示编译警告:

复制代码
csharp


复制代码
var example = new Example();
example.OldMethod(); // 警告:Use NewMethod instead.

示例 2:[Serializable]

标记类为可序列化的类。

复制代码
csharp


复制代码
[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

示例 3:[DllImport]

用于调用非托管代码(例如 DLL 文件)。

复制代码
csharp


复制代码
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll")]
    public static extern int MessageBox(int hWnd, string text, string caption, int type);

    static void Main()
    {
        MessageBox(0, "Hello, World!", "PInvoke Example", 0);
    }
}

2. 自定义特性

定义自定义特性

继承自 System.Attribute 类。

复制代码
csharp


复制代码
using System;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
    public string Description { get; }

    public MyCustomAttribute(string description)
    {
        Description = description;
    }
}
使用自定义特性

将特性应用到类或方法。

复制代码
csharp


复制代码
[MyCustomAttribute("This is a test class.")]
public class TestClass
{
    [MyCustomAttribute("This is a test method.")]
    public void TestMethod()
    {
        Console.WriteLine("Test method executed.");
    }
}
读取特性信息(通过反射)

使用反射动态获取特性信息。

复制代码
csharp


复制代码
using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        var type = typeof(TestClass);
        var attributes = type.GetCustomAttributes<MyCustomAttribute>();

        foreach (var attr in attributes)
        {
            Console.WriteLine($"Class Attribute: {attr.Description}");
        }

        var method = type.GetMethod("TestMethod");
        var methodAttributes = method.GetCustomAttributes<MyCustomAttribute>();

        foreach (var attr in methodAttributes)
        {
            Console.WriteLine($"Method Attribute: {attr.Description}");
        }
    }
}

3. 特性参数

特性可以接受位置参数命名参数

复制代码
csharp


复制代码
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute
{
    public string LogLevel { get; }
    public bool IsEnabled { get; set; }

    public LogAttribute(string logLevel)
    {
        LogLevel = logLevel;
    }
}

使用特性时:

复制代码
csharp


复制代码
public class Demo
{
    [Log("Info", IsEnabled = true)]
    public void DoSomething()
    {
        Console.WriteLine("Doing something...");
    }
}

4. 常见内置特性

|----------------------------|-------------------------------------|
| 特性名称 | 说明 |
| [Obsolete] | 标记某方法或类为过时,提示开发者使用替代方案。 |
| [Serializable] | 指定类可以被序列化。 |
| [NonSerialized] | 用于字段,表示不参与序列化。 |
| [Conditional] | 控制条件编译,常用于调试日志等场景。 |
| [DllImport] | 用于声明调用非托管代码(PInvoke)。 |
| [Flags] | 标记枚举可以按位组合使用。 |
| [DebuggerStepThrough] | 告诉调试器跳过此代码段,不进入代码执行。 |
| [TestMethod] | 标记方法为单元测试方法(在 MSTest 框架中使用)。 |
| [HttpGet] , [HttpPost] | 用于 ASP.NET Core 控制器方法,标记 HTTP 请求类型。 |


特性使用的高级场景

1. 控制序列化行为

通过特性控制类或字段在序列化中的表现。

复制代码
csharp


复制代码
[Serializable]
public class Employee
{
    public string Name { get; set; }

    [NonSerialized]
    public int TempData; // 不会被序列化
}

2. 条件编译

在某些场景下,控制代码是否编译或执行。

复制代码
csharp


复制代码
using System.Diagnostics;

public class Example
{
    [Conditional("DEBUG")]
    public void LogDebugInfo()
    {
        Console.WriteLine("Debugging info...");
    }
}

3. ASP.NET Core 特性

ASP.NET Core 中,特性广泛用于控制路由、验证、授权等行为。

复制代码
csharp


复制代码
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "Sunny", "Rainy" };
    }
}

总结

  1. 特性是元数据:用于为代码添加描述性信息或控制行为。
  2. 易扩展性:可以通过自定义特性满足复杂需求。
  3. 结合反射:在运行时可以动态读取特性信息,适合灵活场景。
  4. 应用广泛:从简单的标记到复杂的框架行为控制,特性都能胜任。
相关推荐
arbboter1 小时前
【自动化】深入浅出UIAutomationClient:C#桌面自动化实战指南
运维·c#·自动化·inspect·uiautomation·uia·桌面自动化
文弱书生6562 小时前
5.后台运行设置和包设计与实现
服务器·开发语言·c#
大飞pkz6 小时前
【设计模式】题目小练2
开发语言·设计模式·c#·题目小练
csdn_aspnet8 小时前
MongoDB C# .NetCore 驱动程序 序列化忽略属性
mongodb·c#·.netcore
浪扼飞舟8 小时前
c#基础二(类和对象,构造器调用顺序、访问级别、重写和多态、抽象类和接口)
java·开发语言·c#
余衫马10 小时前
开发指南:使用 MQTTNet 库构建 .Net 物联网 MQTT 应用程序
物联网·mqtt·.net
好望角雾眠11 小时前
第四阶段C#通讯开发-1:通讯基础理论,串口,通讯模式,单位转换,代码示例
开发语言·笔记·c#·串口·通讯
薄荷撞~可乐18 小时前
C#Task(Api)应用
开发语言·c#
William Wang~19 小时前
.net 类库生成的DLL源码混淆加密
.net
almighty271 天前
C#WPF控制USB摄像头参数:曝光、白平衡等高级设置完全指南
开发语言·c#·wpf·usb相机·参数设置