自学内容网 自学内容网

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. 应用广泛:从简单的标记到复杂的框架行为控制,特性都能胜任。

原文地址:https://blog.csdn.net/weixin_41541184/article/details/145160704

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!