03-C#.Net-特性-学习笔记

C#版本与.NET版本对应关系 C#版本与.NET版本版本对应关系 C#版本 .NET版本 发布日期 特性 C# 1.0 .NET Framework 1.0 2002-02-13 委托、事件 C# 1.1 .NET Framework 1.1 2003-04-24 APM(异步编程模型) C# 2.0 .NET Framework 2.0 2005-11-07 泛型、匿名方法、迭代器、可空类型 ... 阅读详情

一、特性的本质

1.1 什么是特性

  • 特性是一个类:直接或间接继承自 Attribute 抽象类
  • 命名规范:类名默认以 Attribute 结尾(使用时可省略)
  • 应用方式:用方括号 [] 包裹,标记在类或类成员上
  • 编译后存在:与注释不同,特性在编译后依然存在于程序集中

1.2 特性 vs 注释

// 注释:编译后不存在,仅用于描述
/// <summary>这是一个Student类</summary>

// 特性:编译后存在,可通过反射获取
[Serializable]  // 标记类可序列化
[Custom(123)]   // 自定义特性
public class Student { }

二、自定义特性

2.1 定义特性类

特性类就是普通的类,继承 Attribute。构造函数参数是标记时的位置参数,公开的属性/字段可以在标记时用命名参数赋值:

// 使用 AttributeUsage 约束特性的使用方式
[AttributeUsage(
    AttributeTargets.All,      // 可标记的目标(类、方法、属性等)
    AllowMultiple = true,      // 是否允许重复标记
    Inherited = true           // 是否可被继承
)]
public class CustomAttribute : Attribute
{
    public string _Name { get; set; }  // 命名参数:标记时可赋值
    public int _Age;                   // 命名参数:标记时可赋值

    public CustomAttribute(int id) { }       // 位置参数

    public CustomAttribute(string name)
    {
        _Name = name;
    }

    public void Do()
    {
        Console.WriteLine("CustomAttribute.Do()");
    }
}

2.2 标记特性

特性可以标记在几乎所有代码元素上:

[Custom(123)]
[CustomAttributeChild]              // 子类特性同样可以用
public class Student
{
    [Custom(123)]
    [Custom(123)]                   // AllowMultiple=true 时允许重复标记
    public int Id { get; set; }

    [Custom("陈大宝")]
    public string Name { get; set; }

    [Custom(123456, _Age = 17)]     // 位置参数 + 命名参数
    public string Description;

    [Custom("山水", _Name = "456789")]
    public void Study() { }

    [return: Custom(123)]           // 标记在返回值上
    public string Answer([Custom(456)] string name)  // 标记在参数上
    {
        return $"This is {name}";
    }
}

2.3 AttributeUsage 详解

AttributeUsage 本身也是一个特性,专门用来约束自定义特性的使用方式,三个参数:

  • AttributeTargets — 指定特性能标记在哪里。常用值:Class、Method、Property、Field、Parameter、All,可用 | 组合多个目标。建议自定义特性时明确指定,避免误用:
[AttributeUsage(AttributeTargets.Property)]                          // 只能标记在属性上
[AttributeUsage(AttributeTargets.Field)]                             // 只能标记在字段上
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]  // 类或方法
  • AllowMultiple — 同一位置是否允许重复标记,默认 false。验证场景里一个属性需要同时标 [Required] 和 [Length],就需要设为 true。

  • Inherited — 子类是否继承父类上的特性,默认 true。StudentVip 继承 Student,Inherited=true 时通过反射也能在 StudentVip 上获取到 Student 的特性。注意:接口上的特性不会被实现类继承,只有类的继承链有效。


三、通过反射调用特性

特性标记后无法直接调用,必须通过反射获取实例才能使用。

关键点:

  • 特性标记 ≠ 执行,反射是让特性生效的唯一途径
  • 先用 IsDefined() 判断是否存在,再用 GetCustomAttributes() 获取实例,避免无谓的对象创建
  • GetCustomAttributes(true) 的 true 参数表示同时搜索继承链;false 只获取当前类型自身的特性
  • 类、属性、字段、方法、参数上的特性都可以通过对应的反射对象获取
public static void Show(Student student)
{
    Type type = student.GetType();

    // 获取类上的特性
    if (type.IsDefined(typeof(CustomAttribute), true))
    {
        foreach (CustomAttribute attr in type.GetCustomAttributes(true))
        {
            Console.WriteLine(attr._Name);
            attr.Do();  // 通过反射拿到实例后才能调用方法
        }
    }

    // 获取属性上的特性
    foreach (PropertyInfo prop in type.GetProperties())
    {
        if (prop.IsDefined(typeof(CustomAttribute), true))
        {
            foreach (CustomAttribute attr in prop.GetCustomAttributes(true))
                attr.Do();
        }
    }

    // 获取字段上的特性
    foreach (FieldInfo field in type.GetFields())
    {
        if (field.IsDefined(typeof(CustomAttribute), true))
        {
            foreach (CustomAttribute attr in field.GetCustomAttributes(true))
                attr.Do();
        }
    }

    // 获取方法参数上的特性
    foreach (MethodInfo method in type.GetMethods())
    {
        foreach (ParameterInfo para in method.GetParameters())
        {
            if (para.IsDefined(typeof(CustomAttribute), true))
            {
                foreach (CustomAttribute attr in para.GetCustomAttributes(true))
                    attr.Do();
            }
        }
    }
}

四、特性的两大核心用途

用途一:获取额外信息(枚举描述)

问题: 数据库存数字(1、2、3),界面要显示文字描述。传统 if-else 的问题:

// 传统方式 ❌
if (userState == UserStateEnum.Normal)
    Console.WriteLine("正常状态");
else if (userState == UserStateEnum.Frozen)
    Console.WriteLine("已冻结");
// 问题:分支多、修改描述需要改多处

解决: 把描述直接标记在枚举字段上,反射+扩展方法统一读取。

// 1. 定义描述特性,只允许标记在字段上
[AttributeUsage(AttributeTargets.Field)]
public class RemarkAttribute : Attribute
{
    private string _Description;
    public RemarkAttribute(string description) => _Description = description;
    public string GetRemark() => _Description;
}

// 2. 标记枚举
public enum UserStateEnum
{
    [Remark("正常状态")] Normal  = 1,
    [Remark("已冻结")]   Frozen  = 2,
    [Remark("已删除")]   Deleted = 3,
    [Remark("其他")]     Other   = 4
}

// 3. 扩展方法封装反射逻辑,调用方无需关心反射细节
public static class RemarkAttributeExtension
{
    public static string GetRemark(this Enum @enum)
    {
        Type type = @enum.GetType();
        FieldInfo field = type.GetField(@enum.ToString());

        if (field.IsDefined(typeof(RemarkAttribute), true))
        {
            RemarkAttribute attr = field.GetCustomAttribute<RemarkAttribute>();
            return attr.GetRemark();
        }
        return @enum.ToString(); // 没有标记就返回枚举名称本身
    }
}

// 4. 使用
UserStateEnum state = UserStateEnum.Frozen;
Console.WriteLine(state.GetRemark()); // 输出:已冻结

// 在实体中直接暴露描述属性
public class UserInfo
{
    public UserStateEnum State { get; set; }
    public string UserStateDescription => State.GetRemark();
}

新增枚举值只加一行 [Remark("xxx")],描述改了只改标记处,获取逻辑完全不用动。


用途二:获取额外功能(数据验证)

问题: 保存前需要验证字段,传统 if 判断的问题:

  • 字段多了代码量爆炸
  • 验证逻辑散落各处,无法复用

解决: 把验证规则标记在属性上,反射统一执行。

// 1. 抽象基类定义统一接口(开闭原则:扩展新规则只需继承,不改已有代码)
public abstract class AbstractAttribute : Attribute
{
    public abstract ApiResult Validate(object oValue);
}

public class ApiResult
{
    public bool Success { get; set; }
    public string ErrorMessage { get; set; }
}

// 2. 具体验证规则
[AttributeUsage(AttributeTargets.Property)]
public class RequiredAttribute : AbstractAttribute
{
    public string _ErrorMessage;
    public RequiredAttribute(string message) => _ErrorMessage = message;

    public override ApiResult Validate(object value)
    {
        bool ok = value != null && !string.IsNullOrWhiteSpace(value.ToString());
        return new ApiResult { Success = ok, ErrorMessage = ok ? null : _ErrorMessage };
    }
}

[AttributeUsage(AttributeTargets.Property)]
public class LengthAttribute : AbstractAttribute
{
    public string _ErrorMessage;
    private int _Min, _Max;
    public LengthAttribute(int min, int max) { _Min = min; _Max = max; }

    public override ApiResult Validate(object value)
    {
        if (value == null) return new ApiResult { Success = true };
        int len = value.ToString().Length;
        bool ok = len >= _Min && len <= _Max;
        return new ApiResult { Success = ok, ErrorMessage = ok ? null : _ErrorMessage };
    }
}

// 3. 标记实体属性
public class UserInfo
{
    public int Id { get; set; }

    [Required("Name的值不能为空")]
    public string Name { get; set; }

    [Required("Mobile的值不能为空")]
    [Length(11, 11, _ErrorMessage = "手机号必须为11位数")]
    public string Mobile { get; set; }
}

// 4. 统一验证管理器,只依赖抽象基类
public static class ValidateInvokeManager
{
    public static ApiResult ValiDate<T>(this T t) where T : class
    {
        Type type = t.GetType();

        foreach (PropertyInfo prop in type.GetProperties())
        {
            if (prop.IsDefined(typeof(AbstractAttribute), true))
            {
                object value = prop.GetValue(t);

                // 一个属性可能有多个验证特性,逐一执行
                foreach (AbstractAttribute attr in prop.GetCustomAttributes())
                {
                    ApiResult result = attr.Validate(value);
                    if (!result.Success)
                        return result; // 遇到第一个失败立即返回
                }
            }
        }

        return new ApiResult { Success = true };
    }
}

// 5. 使用
UserInfo user = new UserInfo { Id = 1, Name = "张三", Mobile = "123" };
ApiResult result = ValidateInvokeManager.ValiDate(user);
if (!result.Success)
    Console.WriteLine(result.ErrorMessage); // 手机号必须为11位数

要新增验证规则(如正则、数字范围),只需新建一个继承 AbstractAttribute 的类,ValidateInvokeManager 完全不用改。


五、特性在自定义 ORM 中的应用

问题: 数据库表名/字段名与类名/属性名不一致,ORM 无法自动映射。

解决: 用特性标记映射关系,ORM 通过反射读取特性生成正确的 SQL。

// 定义映射特性
[AttributeUsage(AttributeTargets.Class)]
public class TableNameAttribute : Attribute
{
    public string Name { get; }
    public TableNameAttribute(string name) => Name = name;
}

[AttributeUsage(AttributeTargets.Property)]
public class ColumnNameAttribute : Attribute
{
    public string Name { get; }
    public ColumnNameAttribute(string name) => Name = name;
}

// 标记实体
[TableName("LM_User")]
public class SysUser : BaseModel
{
    [ColumnName("user_name")]  public string Name  { get; set; }
    [ColumnName("user_phone")] public string Phone { get; set; }
}

// ORM 查询时通过反射读取特性生成 SQL
public T Find<T>(int id) where T : BaseModel
{
    Type type = typeof(T);

    string tableName = type.IsDefined(typeof(TableNameAttribute), false)
        ? type.GetCustomAttribute<TableNameAttribute>().Name
        : type.Name;

    var columns = type.GetProperties().Select(p =>
        p.IsDefined(typeof(ColumnNameAttribute), false)
            ? p.GetCustomAttribute<ColumnNameAttribute>().Name
            : p.Name);

    string sql = $"SELECT {string.Join(",", columns)} FROM {tableName} WHERE Id={id}";
    // ... 执行查询并反射赋值
}

泛型缓存优化反射性能: 同一类型的 SQL 模板每次查询都一样,没必要每次都反射。用泛型类的静态构造函数缓存结果,同一类型只反射一次:

public class ConstantSqlString<T>
{
    private static readonly string FindSql;

    static ConstantSqlString()
    {
        // 静态构造函数只执行一次,之后直接读缓存
        Type type = typeof(T);
        FindSql = $"SELECT {string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"))} FROM {type.Name} WHERE Id=";
    }

    public static string GetFindSql(int id) => $"{FindSql}{id}";
}

// 使用
string sql = ConstantSqlString<SysUser>.GetFindSql(1);

ConstantSqlString<SysUser> 和 ConstantSqlString<SysCompany> 是两个独立的类,各自有独立的静态字段,互不干扰,线程安全由 CLR 的类型初始化机制保证,无需加锁。


六、核心总结

特性的三大核心步骤

  1. 定义特性:继承 Attribute,用 AttributeUsage 约束使用范围
  2. 标记特性:用 [] 标记在目标上,传位置参数或命名参数
  3. 反射调用:运行时通过反射获取特性实例,执行其中的逻辑

特性的两大价值

  1. 获取额外信息:枚举描述、配置信息、映射关系
  2. 获取额外功能:数据验证、AOP 切面、权限控制

最佳实践

  • 明确指定 AttributeTargets,告诉使用者这个特性用在哪里
  • 先用 IsDefined() 判断再获取,避免无谓的对象创建
  • 用扩展方法封装反射调用逻辑,对外暴露干净的 API
  • 用抽象基类统一处理同类特性,保持可扩展性
  • 反射有性能开销,高频调用场景用泛型缓存优化

常见框架中的特性速查

场景常见特性
序列化[Serializable]
ASP.NET Core MVC[HttpGet] [Route] [Authorize] [FromBody]
依赖注入[Inject] [Service]
ORM(EF Core)[Table] [Column] [Key] [ForeignKey]
数据验证[Required] [Range] [StringLength] [EmailAddress]
C#新手营——1.C#简介 1.C#是什么 C#是微软公司开发的一种面向对象且类型安全的高级程序设计语言,它运行于.NET Framework和.NET Core平台。 2..NET体系结构 3.类型和变量 4.程序执行 5.版本特色 6.C#的特点与优势 ... 阅读详情

相关推荐

2021-05-24 .NET高级班 03-特性

一:基本使用执行特性中的方法 //----------------基本使用执行特性中的方法-------------------- Student student = new Student(); Student studentVip = new StudentVip() { Id = 1, Name = "热爱学习", VipGroup = ".Net vip" }; InvokeCenter.ManagerSudent<Student>(studentVip); /// &lt

愚公智库 52万+

C#版本与.NET版本对应关系以及各版本的特性

C#版本与.NET版本对应关系以及各版本的特性及修改C#语言版本方法

hpx666的博客 4091

基于C#与.NET Core的OPC UA 1.03客户端开发实战指南

在工业自动化与物联网领域,数据采集是连接物理设备与信息系统的关键技术。其核心原理在于通过标准化的通信协议,实现设备数据的可靠、安全读取与传输。OPC UA作为一种跨平台、支持语义信息模型的工业通信标准,其技术价值在于解决了传统OPC DA在安全性、跨平台性等方面的局限,为构建统一的数据底座提供了基础。在应用场景上,它广泛服务于制造执行系统、设备监控和工业互联网平台的数据集成。本文聚焦于使用C#语言和.NET Core框架,开发一个兼容OPC UA 1.03规范的客户端,详细阐述了从连接管理、数据订阅到跨平台

weixin_42525369的博客 257

C# 学习笔记

MicrosoftVisualStudio(简称VS)是美国微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,是编写C#程序或者说.NET程序最常用的开发工具。因其功能强大、简单易用、速度快、智能度高,被网友戏称宇宙第一IDE。

qq_52144597的博客 2046

IoTDB时序数据库在Windows下的保姆级安装教程(含环境变量配置避坑指南)

本文提供Apache IoTDB时序数据库在Windows系统下的详细安装与配置指南。教程涵盖从Java环境检查、软件下载解压,到环境变量配置的深度避坑,并详解了服务的启动、停止、连接测试及基础数据操作,帮助物联网开发者在Windows平台快速搭建稳定的时序数据库环境。

weixin_29275257的博客 260

MobileNet V3 图像分类

MobileNet V3

Henry的博客 1767

.NET 10 重磅特性:无需项目的C#脚本执行方案

.NET 10新特性:dotnetrunapp.cs简化C#开发 .NET 10 Preview 4推出dotnetrunapp.cs功能,允许开发者直接运行单个C#文件,无需创建项目文件或复杂目录结构。通过文件级指令(如#:package引用NuGet包、#:sdk指定SDK),可快速构建脚本或小型应用,并支持shebang行跨平台执行。当代码复杂度增加时,使用dotnetprojectconvert无缝转换为完整项目。此功能降低C#入门门槛,保留与标准项目的一致性,为学习、实验和脚本开发提供高效方案。安

weixin_41541184的博客 2189

Lisflood

文献:基于SWMM和LISFLOOD-FP模型的居住区低影响开发模拟评价。问题:多个节点溢流同时,不行,待解决。目录下,cmd命令行。

警警的博客 2660

C#1.0至11.0所有历史版本主要特性一句话总结

自从2002年.Net平台发布开始,C#已经从1.0更新到了现在的11.0。目前网上有很多文章对这些版本的主要更新内容进行了总结,但是大都是内容的简单翻译和资料堆叠。本文根据自己的使用体验,在现有总结的基础上进行内容丰富细化,以便于读者能够对C#的语言特性有更加详细深刻的认识和理解。

郝伟老师的博客——大数据、并行计算与人工智能时代 1万+

结构光三维重建2——多频外差解包裹

本文深入解析了结构光三维重建中的多频外差解包裹技术。针对四步相移法产生的相位包裹问题,该方法通过投影多组不同频率的条纹光,利用外差原理逐级解算,最终获得精确、连续的绝对相位值,是实现高精度、稳健三维重建的关键步骤。

weixin_29056101的博客 350

STM32F407+HAL库+W5500实现TCP通讯 个人项目总结

推荐阅读此博客 cv即可成功首先需要一个可以进行串口调试的工程,方便进行调试。1.在W5500官网移植库文件重点是Ethernet这个文件夹将里面的 socket.c,socket.h,wizchip_conf.c,wizchip_conf.h,还有根据W5500文件夹里的w5500.c和w5500.h移植到自己的工程里面。然后再创建一个.c和.h文件 我的叫w5500_port_hal.c 和w5500_port_hal.h 记得将.h文件链接到工程里。

a234abr的博客 2246

C#入门01篇——(1).net是什么东西 是用来干嘛的啊(2).net和c#的区别 (3).NET、C#和ASP.NET三才之间的区别

参考: 博文01:https://zhidao.baidu.com/question/314437641.html 博文02:https://blog.csdn.net/weixin_42538115/article/details/80884268 博文03:https://blog.csdn.net/279503482/article/details/6007190 博文01: .net 是微...

博雅勇士的博客 1435

从 OPEN CURSOR 到 SELECT INTO TABLE:把 ABAP 数据读取的底层机制与性能差异讲透

ABAP数据库访问性能优化关键点 摘要:ABAP程序性能的核心在于数据读取方式的选择。本文分析了三种常见数据库访问方式的技术原理:显式游标(CURSOR)、SELECT-ENDSELECT循环和SELECT INTO TABLE。重点揭示了数据从数据库到应用服务器的传输机制,包括OPEN/REOPEN与FETCH操作、Array Fetch批量传输原理以及SAP游标缓存机制。通过VBAK表的性能测试数据对比,证明了不同场景下最优访问方式的选择依据:大数据量时显式游标性能优势明显,而SELECT INTO T

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 168

03-C#.Net-特性-面试题

特性编译后以元数据形式存储在程序集中,运行时可以通过反射读取,能携带数据和逻辑,真正影响程序行为。核心设计:抽象基类定义统一接口,具体验证规则继承实现,验证管理器只依赖抽象基类,新增规则不改已有代码。先说核心区别(编译后是否存在),再说本质(是一个类),最后点出标记语法的本质是调用构造函数。说清楚"标记 ≠ 执行",反射是让特性生效的唯一途径,顺带提性能优化(先判断再获取)。考察对特性运行机制的理解,很多人只会标记特性,不知道背后原理。考察对特性基础概念的理解,区分"会用"和"真懂"。

噢~ 555

【Docker】完美解决拉取镜像超时报错:ERROR: Get https://registry-1.docker.io/v2/

因为我们下载的镜像是外网的镜像资源,所以下载的速度会非常的慢,甚至大概率下载时会报错,所以需要我们配置一个国内的服务器镜像地址,国内服务器镜像地址有很多,这里咱们就说一下阿里镜像加速器的配置方法。

liu_chen_yang的博客 12万+

3D打印机控制系统设计:基于MATLAB的3D打印机运动学建模、轨迹规划和控制

控制实现:在控制实现中,需要将轨迹规划的结果转化为实际的控制指令,控制3D打印机按照规划的轨迹进行运动。3D打印机的运动学建模:3D打印机的运动学建模是指将3D打印机的机械结构、传动系统和运动控制部件等抽象成数学模型,以便于进行控制系统的设计和分析。轨迹规划:轨迹规划是指根据3D模型的几何形状和打印机的运动学模型,计算出打印机需要执行的运动轨迹,以便于实现所需的打印效果。控制实现:控制实现是指将轨迹规划的结果转化为控制指令,控制3D打印机按照规划的轨迹进行运动。

走向CTO的路上... 2473

.NET 9 技术革新,新特性概览

NET 9 作为微软推出的最新框架版本,无疑为开发者带来了一系列的新特性,继.NET 8 之后,.NET 9 在云原生应用程序得到了增强和性能得到提升。它是STS版本,将获得为期18个月的标准支持服务。这些新特性究竟有多新颖?它们将如何影响我们的开发实践?本文将探讨.NET 9 的几个关键新特性,可以到官网下载.NET 9。.NET 9引入了针对云原生应用和性能优化的重大增强。通过对序列化、LINQ改进和加密方面的关注,开发人员可以利用新功能和API来简化开发流程并增强应用程序安全性。

DotNet技术匠 2028

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

.NET周报 【3月第1期 2023-03-03】

国内文章我做的FFmpeg开源C#封装库Sdcb.FFmpeghttps://www.cnblogs.com/sdflysha/archive/2023/02/27/dotnet-conf-china-2022-ffmpeg.htmlFFmpeg是知名的音频视频处理软件,我平时工作生活中会经常用到。但同时我也是.NET程序员,我以业界普遍使用的开源项目FFmpeg.AutoGen为基础,我我自己动...

dotNET跨平台 944

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C#.NET版本、Visual Studio版本对应关系

C#版本 .NET版本 Visual Studio版本 发布日期 特性 C# 1.0 .NET Framework 1.0 Visual Studio .NET 2002 2002-02-13 委托、事件 C# 1.1 .NET Framework 1.1 Visual Studio .NET 2003 2003-04-24 APM(异步编程模型) C# 2.0 .NET Framework 2.0 Vis...

Admans的专栏 2134

C#1.0-11.0所有历史版本主要特性总结

从2002年.Net平台发布开始,C#已经从1.0更新到了现在的8.0。目前网上有很多文章对这些版本的主要更新内容进行了总结,但是大都是内容的简单翻译和资料堆叠。本文根据自己的使用体验,在现有总结的基础上进行内容丰富细化,以便于读者能够对C#的语言特性有更加详细深刻的认识和理解。自从上世纪90年代Java火了以后,微信就想做自己的Java,于是从1998年开始就制定了.NET计划,并于2002年正式发布。

Blue 3039

.NET周刊【11月第1期 2024-11-03】

国内文章 .NET 9 AOT的突破 - 支持老旧Win7与XP环境 https://www.cnblogs.com/lsq6/p/18519287 .NET 9 引入了 AOT 支持,使得应用程序能够在编译时优化,以在老旧 Windows 系统上运行。这项技术通过静态编译,消除运行时的 JIT 编译,加速程序执行。尽管 Windows 7 和 XP 已不再主流,它们在某些领域仍被广泛使用。.NET 9 的 AOT 旨在提升兼容性和性能。AOT 编译程序通常执行更快,部署简单,降低了维护成本。项目配置展示了

InCerry的博客 1154
上一篇: 02-C#.Net-反射-面试题
下一篇: 03-C#.Net-特性-面试题
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值