🎯 C# 学习路线
148 个互动教程
C# 入门 — .NET 开发利器
了解 C#:微软现代面向对象语言,.NET 生态核心,游戏/桌面/Web 全栈开发
C# 入门
学习C#基础
C# 变量与类型
值类型、引用类型、var 推断、可空类型
C# 数组与集合
Array/List<T>/Dictionary<K,V>
C# 文件操作
File.ReadAllText/WriteAllText
C# 循环
for/while/foreach/do-while
C# LINQ — 数据查询语法
LINQ:在 C# 中用 SQL 风格的语法查询集合
C# 类与属性
get/set/init/构造函数
C# async/await 异步编程
Task + await 非阻塞异步操作
C# 泛型集合
List<T>/Dictionary<K,V>/约束
C# 委托与事件
delegate/event:回调函数和发布订阅
C# 接口
interface + 多态
C# Task 并行
Task.Run/WhenAll/Parallel.ForEach
C# 集合深入
List/Dictionary/HashSet/Queue
C# Lambda 与 LINQ
=> 表达式 + 查询语法
C# 异常处理
学习C#中C# 异常处理 — C#教程的详细用法和最佳实践
C# 面向对象深入
学习OOP
C# Entity Framework
EF Core ORM: Code First/Migrations/LINQ
ASP.NET Core Web API
[ApiController] + [Route] 构建 REST API
C# LINQ 进阶
GroupBy/Join/Aggregate/SelectMany/PLINQ
C# 依赖注入
IServiceCollection/构造函数注入/生命周期
C# Record 记录类型
C# 9+ Record类型:不可变数据模型、with表达式创建副本、值相等比较(非引用相等)、record struct(C#10)、init-only属性、与class/struct对比
C# 依赖注入 DI
.NET依赖注入:IServiceCollection注册服务、Singleton/Scoped/Transient三种生命周期、构造函数注入、ServiceProvider容器、第三方容器Autofac
C# LINQ 高级查询
LINQ深入:IQueryable<T>表达式树Expression Tree(远程查询)、SelectMany展平、GroupBy分组+聚合、Join/GroupJoin关联、自定义扩展方法、PLINQ并行查询AsParallel
C# 不可变集合
System.Collections.Immutable不可变集合(NuGet包):ImmutableList/ImmutableArray/ImmutableDictionary/ImmutableHashSet/ImmutableStack/ImmutableQueue/Builders构建器批量修改、与ReadOnlyCollection和FrozenSet( .NET 8)对比
C# Expression Trees 表达式树
C# Expression Trees表达式树(代码作为数据/运行时分析编译表达式):Expression<Func<T,bool>>表达式树Lambda、Expression.AndAlso/Expression.Equal/Expression.Property/Expression.Constant动态构建表达式树、IQueryable LINQ提供者(EF Core/IQueryable<
C# 入门 — .NET环境搭建与第一个程序
C#与.NET简介、安装.NET SDK、dotnet CLI命令(new/run/build)、IDE选择(Visual Studio/VS Code+Rider)、第一个Hello World
C# 可空类型与Null处理
C#可空类型:Nullable<T>/T?、??空合并运算符、??=空合并赋值、?.空条件运算符、string?引用类型可空(.NET 6+)、Null/NotNull特性标注
C# Record 类型详解
学习C# Record类型,掌握不可变数据模型和值相等性
C# LINQ 查询入门
C# LINQ:查询语法vs方法语法、Where筛选/Select映射/OrderBy排序/GroupBy分组/Join连接/Aggregate聚合、First/SingleOrDefault、延迟执行vs立即执行
C# 模式匹配进阶
学习C#模式匹配语法,包括类型匹配、属性匹配和列表模式
C# async/await 异步编程
C#异步编程:Task<T>、async/await、ConfigureAwait(false)、WhenAll并行/WhenAny竞速、取消CancellationToken、异步方法命名规范(Async后缀)
C# 顶级语句入门
学习C#顶级语句,简化控制台应用程序的入口点
C# 属性和索引器
C#属性:自动属性{get;set;}、只读/只写属性、表达式体属性=>、init访问器(不可变)、计算属性、索引器this[int i](像数组一样访问对象)
C# init 访问器详解
学习C# init-only 属性,实现对象初始化器后的不可变性
C# 委托与事件
C#委托:delegate定义/Func/Action/Predicate内置委托、多播委托+=/-=、event事件(发布-订阅模式)、EventHandler标准模式、匿名方法/lambda
C# Span<T> 高效内存操作
学习Span<T>和ReadOnlySpan<T>,实现零分配的内存切片操作
C# 集合与泛型集合
C#集合:ArrayList/Hashtable(非泛型/已过时)、List<T>/Dictionary<TKey,TValue>/HashSet<T>/Queue<T>/Stack<T>泛型集合、LINQ配合集合、IEnumerable<T>接口
C# Record Struct 值类型数据模型
学习C# record struct,创建具有值语义和不可变性的轻量级类型
C# 源生成器入门
学习C#源生成器,在编译时自动生成代码
C# 可空引用类型
学习C#可空引用类型,在编译时防止空引用异常
C# 异步流 IAsyncEnumerable<T>
学习C#异步流,使用await foreach处理异步数据序列
C# Native AOT 编译
学习C# Native AOT,将.NET应用编译为原生机器码
C# Record 类型详解
掌握 C# 9 引入的 Record 类型,理解其值相等性、不可变性和 with 表达式。
C# Span<T> 与内存高效处理
学习使用 Span<T> 和 Memory<T> 进行无分配的内存切片操作,提升性能。
C# Span<T> 高效内存操作
学习使用 Span<T> 进行无分配的内存切片操作,提升性能。
C# Record 类型详解
学习 C# 9 引入的 record 类型,掌握不可变数据建模与值相等性比较。
C# Span<T> 高效内存操作
学习 Span<T> 和 ReadOnlySpan<T>,实现无分配的内存切片操作,提升性能。
编码幻象:C# 中引用类型与值类型的记忆陷阱
深入剖析堆栈内存分配如何影响值类型与引用类型的复制行为,并通过构造看似违背直觉的代码场景揭示隐式装箱与内存碎片。
不安全的浪漫:用指针编写高效数组切片
挑战托管安全的边界,利用fixed语句和指针算术实现比Span<T>更低开销的数组视图,同时揭示GC对固定对象的跟踪机制。
泛型代数:利用静态抽象接口实现数学类型族
利用.NET 7引入的静态抽象接口方法,在泛型约束中定义运算符重载,从而为任意数值类型创建通用的数学运算库。
等待机:手动构建状态机理解async/await底层
不依赖编译器生成的异步状态机,从零开始实现一个支持await的自定义Task-like类型,揭示异步方法的真正执行流程。
源代码补丁:运行时修改Lambda表达式的AST
利用Roslyn的Syntax API在运行时解析Lambda表达式并替换其语法节点,实现类似AOP的拦截效果而不使用反射或Emit。
内联数组魔法:在结构体中嵌入固定大小缓冲区
利用unsafe的fixed与.NET 7的InlineArrayAttribute,在栈上创建高性能的固定大小数组,避开堆分配和边界检查。
拦截者织入:利用Source Generator无侵入记录方法调用
编写一个Roslyn Source Generator,自动为指定方法生成调用前后日志的包装代码,无需手动修改原方法体。
低层分配器:实现自定义对象池避免GC压力
超越ConcurrentQueue的简单池化,利用数组+原子操作构建无锁对象池,并处理重置对象状态与线程本地缓存。
联合类型戏法:用结构体布局实现C风格联合体
通过StructLayout(LayoutKind.Explicit)与FieldOffset特性,在C#中模拟C语言的union,实现内存覆盖的多类型数据存储。
替代互操作:用函数指针实现原生回调而不使用委托
利用delegate*语法与UnmanagedCallersOnly,在P/Invoke场景中传递原始函数指针,避免委托分配和参数打包。
C#中的任意精度整数运算与BigInteger进阶
深入探讨System.Numerics.BigInteger在加密算法、大数计算中的高级用法,包括性能优化、内存管理和与原生类型的互操作。
Roslyn源生成器:编译时元编程实战
讲解如何利用Roslyn分析器在编译期间生成C#代码,实现自动实现接口、序列化代码生成等高级场景,并处理增量生成器缓存。
Span<T>与Memory<T>极致性能优化
超越基本用法,探讨如何在网络协议解析、图像处理等场景中利用Span<T>实现零分配、栈上buffer、以及连续内存的切片和互转换。
Channel<T>实现高吞吐实时数据流管道
使用System.Threading.Channels构建生产者-消费者模式,支持背压、多路复用和取消,适用于日志收集、传感器数据处理等场景。
函数指针与unmanaged委托的底层互操作
详解C# 9.0引入的函数指针以及unmanaged委托在游戏引擎、嵌入式开发中的底层调用和性能优势。
模式匹配穷尽性分析与代数数据类型
利用C# 8.0+的模式匹配实现类似代数数据类型的穷尽性检查,在状态机、协议解析中保证安全性。
ref struct与内存所有权模型
深入ref struct的限制和用途,设计类似Span<T>的自定义值类型以及处理栈上资源所有权的模式。
静态抽象接口与泛型数学(.NET 7+)
基于.NET 7的INumber<T>接口,讲解如何创建支持泛型数学运算的高性能类型,重载运算符的静态抽象模式。
NativeAOT编译:零运行时依赖的部署方案
讲解.NET 7+ NativeAOT的原理、限制和应用,包括与反射的冲突处理、配置Trimming、以及生成最小体积原生二进制。
Unsafe代码与Span<T>:构建高性能C互操作层
利用unsafe代码和Span<T>设计零GC、零拷贝的C语言互操作层,适用游戏、图像处理等场景。
引用返回与引用局部变量:超越值类型的性能优化
深入探讨 ref returns 和 ref locals 在大型结构体处理、避免副本拷贝以及内存地址直接操作中的应用。
函数指针与不安全委托:当性能成为第一需求
讲解 C# 9+ 的 function pointers(delegate*)语法及其与不安全代码的结合,用于高性能互操作场景。
泛型特性与类型反射:编译时类型安全的元数据编程
探讨 C# 11 的泛型特性(Generic Attributes)如何结合反射实现类型安全的元数据注入。
原始字符串字面量与自定义插值处理器:模板引擎的终极形态
深入 C# 11 的原始字符串字面量(""")和自定义插值字符串处理器,构建安全高效的模板系统。
列表模式与递归模式匹配:函数式数据解析的利器
探索 C# 11 的列表模式及嵌套模式匹配,用于解析复杂数据结构如 AST 或 JSON。
必需成员与仅初始化设置器:不可变对象的设计新范式
详解 C# 11 的 required 修饰符与 init 访问器如何实现编译时强制填充的不可变类型。
IAsyncEnumerator 与深度取消协作:异步数据流编舞
探讨自定义异步枚举器的实现及 CancellationToken 如何贯穿异步流,实现精确的作业控制。
全局 using 与别名 any 类型:简化复杂泛型签名
利用 global using 和 using alias 为复杂泛型(如嵌套字典)创建可读的短名称,改善代码维护性。
拦截器与源生成器:编译时代码重写的高级应用
探索 C# 实验性特性拦截器(Interceptors),结合源生成器实现 AOP 风格的方法替换。
冻结集合与不可变集合的极致性能:内存布局与并发优化
分析 FrozenSet/FrozenDictionary 的内部实现与不可变集合的性能差异,应对高频只读查询场景。
ref struct 与栈上内存布局的艺术
深入剖析 C# 7.2 引入的 ref struct,讲解其在 Span<T> 生态中的核心地位、栈上分配限制以及如何通过自定义布局避免装箱与堆分配。
函数指针与原生回调的零开销互操作
详解 C# 9 的 delegate* 语法,对比传统委托的性能损失,在图像处理、音频流等场景中用函数指针直接传递 C++ 回调。
泛型数学接口:让算法真正通用
探索 .NET 7 中 IAdditionOperators、IMultiplicativeIdentity 等静态抽象接口,实现一个适用于任意数值类型的泛型矩阵乘法。
源生成器:编译期的元编程工厂
从零构造一个源生成器,自动为标记 [AutoNotify] 的字段生成 PropertyChanged 通知,深入理解 IncrementalGenerator 与管道式生成。
unsafe Span 与数组别名:跨越托管边界
利用 MemoryMarshal 和 Unsafe 类创建跨越不同类型的内存视图,实现无拷贝的字节到结构体转换,探索类型别名的底层原理。
ValueTask 生命周期与任务对象池
揭示 ValueTask 正确使用的陷进,实现一个可池化的 IValueTaskSource 让异步方法零分配,在高吞吐服务器中极致优化。
Caller Info 特性与 P/Invoke 日志注入
利用 CallerMemberName、CallerFilePath 等特性自动记录原生调用点,构建一个非侵入式的调试助手,无需手动传递文件名。
编译期正则:GeneratedRegex 的幕后与定制
分析 .NET 7 中 [GeneratedRegex] 源生成器的原理,并手动实现一个针对特定模式的编译期正则生成器,比较与运行时 Regex 的发射与性能。
默认接口方法:钻石问题与混合继承
深入 C# 8 的默认接口方法如何解决多继承冲突,并探讨其与 trait 系统的异同,构建一个带默认行为的插件系统。
只读记录结构体:值相等与自定义哈希策略
剖析 readonly record struct 的自动生成 Equals/GetHashCode,并演示如何通过重写 EqualityContract 实现仅部分字段参与比较。
Span<T> 与 Memory<T>:零分配内存操作的高级模式
深入讲解 Span<T> 和 Memory<T> 如何在堆栈上安全地操作连续内存,避免堆分配和复制,适用于高性能场景如网络解析、图像处理和序列化。
函数指针与托管回调:跨语言调用的零开销桥接
探索 C# 9 引入的函数指针(delegate*)语法,如何在需要极致性能的互操作场景中替代委托,减少间接调用开销,并配合 UnmanagedCallersOnly 实现原生回调。
Roslyn 源生成器:编译时生成代码的元编程革命
讲解如何编写增量源生成器,在编译期间分析语法树并生成额外文件,避免反射和运行时性能损失。涵盖常见模式如自动实现 INotifyPropertyChanged 和依赖注入注册。
ref struct 与只读约束:构建零堆分配的不可变数据类型
深入探讨 ref struct 的堆栈限制如何用于创建高性能、确定性释放的数据结构,如类似 ReadOnlySpan 的自定义类型,并利用 in 参数和 readonly 成员实现安全共享。
静态抽象接口成员:泛型数学与运算符重载的泛化
C# 11 引入的静态抽象接口成员使泛型类型可以要求运算符,实现真正的泛型数学。本教程展示如何定义 INumeric<T> 接口并编写通用算法,同时兼容框架内置数值类型。
Record 结构体:值语义、声明式不变性与性能权衡
C# 10 的 record struct 结合了结构体性能与记录的值相等语义。本教程对比 record class 与 record struct,分析自动生成的相等性、ToString 和 Deconstruct 的内部实现,并讨论何时使用避免装箱。
LibraryImport:P/Invoke 源生成的新一代原生互操作
弃用 DllImport,使用 LibraryImport 特性在编译时生成互操作代码,消除运行时 DLL 查找开销,自动处理编组和安全转换。本教程涵盖自定义编组器和 UTF-8 字符串传递。
IAsyncEnumerable 进阶:自定义异步流生成器与高级取消模式
超越简单 await foreach,探讨如何编写 yield return 式异步流,实现节流、批处理和可恢复流,利用 CancellationToken 回调实现细粒度取消。
泛型属性与类型约束:设计编译时安全的元数据标记
C# 11 允许在属性中使用泛型类型参数,结合 where 约束实现静态验证。本教程展示如何使用泛型属性标记枚举值、方法或类,并通过反射获取类型化信息,避免运行时类型检查。
正则表达式源生成器:编译时解析与零运行时开销匹配
.NET 7 的正则表达式源生成器将正则模式编译为 C# 代码,消除解释阶段且避免反射。本教程比较传统 Regex 与 GeneratedRegex 的性能,并讲授如何编写复杂模式并通过调试器查看生成的优化代码。
ref struct 与栈上高性能数据模式
深入 ref struct 的限制、Span<T> 交互与栈分配优化
函数指针 delegate* 与非托管调用约定
学习 C# 9 函数指针语法、调用约定选型和 AOT 场景应用
CallerArgumentExpression 与精确错误诊断
利用编译器生成的表达式信息在断言/验证中输出参数原始代码文本
泛型数学与静态抽象接口成员
C# 11 静态抽象接口成员实现通用数值运算,告别重复重载
内插字符串处理器与自定义日志格式化
利用 InterpolatedStringHandler 实现条件日志、安全格式化与零分配构建
源生成器覆写:从特性生成反射等效代码
用 Roslyn 源生成器分析特性并生成强类型序列化/验证代码
零拷贝 JSON 序列化:Utf8JsonReader 与序列化器构建
手写高性能 JSON 解析器,使用 SequenceReader 和按需生成
内联数组:stackalloc 进阶与固定大小缓冲区
C# 12 内联数组特性在栈上创建固定大小连续数据,超越传统数组
自定义 Task-like 类型与异步流式管道
利用 AsyncMethodBuilder 实现零分配异步操作与自定义调度器
托管指针算术:ref 参数的偏移与迭代
使用 ref 进行安全指针运算,构造通用多维跨度访问器
Span<T> 与 Memory<T>:零分配字符串处理
深入 Span<T> 和 Memory<T> 如何在不创建新字符串的情况下高效解析、切片和修改字符串,避免GC压力。
ref struct 与栈上类型:安全的高性能数据容器
探索 ref struct 如何被限制在栈上分配,避免装箱和堆引用,创建高性能临时数据结构。
函数指针 (delegate*):取代委托的零开销回调
学习使用 unsafe 上下文中的函数指针类型,实现比委托更快的方法调用,适合互操作和高频回调场景。
内插字符串处理器:自定义高性能日志构建器
利用 InterpolatedStringHandler 模式创建条件日志、内存池化的字符串构造,避免无意义的格式化。
泛型数学:INumber<T> 与静态抽象接口方法
基于静态抽象接口方法实现泛型数学运算,编写适用于 int、double、decimal 的通用计算器。
源代码生成器:编译时自动生成样板代码
使用 Roslyn 分析器在编译阶段生成代码,消除反射和手动编写的重复逻辑(如自动 INotifyPropertyChanged、DTO 映射)。
集合表达式与展开运算符:全新的列表、字典创建语法
深入 C# 12 的集合表达式语法 [...] 以及展开运算符 .. 如何简化数组、Span、列表的初始化。
高级 Native AOT 互操作:自定义编组器与源生成
利用 LibraryImport 和自定义 marshaller 在 Native AOT 中高效调用 C 库,避免运行时编组开销。
record struct:值类型相等性、克隆与 with 表达式
解析 record struct 如何提供自动值相等性、拷贝语义和 with 表达式,适合不可变数据结构。
高级异步流:IAsyncEnumerable 与协作式取消
超越基础,实现带取消令牌、速率限制和背压的异步流,处理分页API和大文件逐行读取。
高阶类型模拟:用泛型构造类型构造器
C# 本身不支持高阶类型(higher-kinded types),但可以通过泛型参数和静态接口模拟。本教程展示如何用泛型工厂模式实现类似 Haskell 中 Functor 的映射操作。
零分配内联互操作: stackalloc 与 Span<T> 的深层结合
如何在没有显式 unsafe 块的情况下使用 stackalloc 分配栈内存,并利用 Span<T> 安全地与原生内存、托管数组进行零拷贝转换,避免 GC 压力。
编译期正则引擎:用源生成器消除运行时反射
利用 Roslyn 源生成器在编译时解析正则表达式并生成强类型匹配方法,避免 Regex 运行时的表达式编译和反射开销。
函数指针回调:取代委托的高性能原生互操作模式
利用 C# 9+ 的 function pointer (delegate*<...>) 语法在 unsafe 上下文中创建无需装箱的纯托管回调,适用于高频 native 回调场景。
代数数据类型:用泛型记录构建类型安全的变体(Discriminated Union)
通过嵌套泛型记录和静态工厂方法,在 C# 中实现功能完整的代数数据类型,支持模式匹配与穷举检查。
固定大小缓冲区:在结构体中嵌入大型数组避免堆分配
使用 unsafe 固定大小缓冲区(fixed buffer)在 struct 中嵌入超过 32 字节的内联数组,实现完全栈上分配的高性能数据结构。
内插字符串处理程序:用 ref struct 实现零分配日志格式化
通过实现自定义的内插字符串处理程序(InterpolatedStringHandler),避免日志框架在不需要输出时执行字符串格式化。
NativeAOT 下的 COM 互操作:脱离运行时生成 vtable
当使用 NativeAOT 发布时,运行时不再提供 COM 包装。本教程展示如何手动构造 COM 接口的 vtable 并实现 QueryInterface、AddRef、Release。
深入空值流分析:自定义注解实现精确可空性追踪
通过 MemberNotNull、MaybeNull、NotNullWhen 等属性指导编译器进行更精准的静态空值分析,消除不必要的 null 检查。
运行时代码生成:用 IL Emit 构建无反射的对象映射器
利用 System.Reflection.Emit 在运行时生成高效的 IL 代码,实现远快于反射的属性赋值/取值,打造轻量级 ORM 或序列化器。
ref struct 的深入语义与栈上生命周期管理
探讨 ref struct 的限制、Span<T> 的内在实现、栈上分配与逃逸分析,以及如何利用 ref struct 构建零开销抽象。
泛型数学接口与自包含抽象:INumber<T> 的底层原理
解析 .NET 7 引入的泛型数学接口,包括 INumber<T>、IFloatingPoint<T> 等,以及如何利用 static abstract interface members 实现高性能泛型数值算法。
函数指针 (delegate*) 与原生互操作的零开销调用
讲解 C# 9 引入的函数指针类型 delegate*,与委托的区别,如何用于高性能回调与非托管互操作,以及安全性考量。
CallerArgumentExpression:自动捕获参数表达式用于断言与日志
介绍 C# 10 的 CallerArgumentExpressionAttribute,如何自动捕获调用者传入的表达式字符串,用于自定义断言、验证和结构化日志。
拦截器 (Interceptors):编译时 AOP 与零开销方法替换
解析 C# 12 的拦截器预览特性,如何在编译期间拦截任意方法调用并替换实现,适用于横切关注点与性能敏感场景。
内联数组 (InlineArray):栈上限定的固定大小缓冲区
介绍 C# 12 的 InlineArray 特性,用于在 struct 内声明固定长度的数组,避免堆分配,适用于高性能数据处理与互操作。
Random.Shared 的线程安全与性能博弈:重新认识静态随机数
深入分析 Random.Shared 在多线程下的行为、线程局部存储的代价,以及如何选择随机数生成策略。
源代码生成器的高级惯用法:增量生成、缓存与持久化状态
超越入门教程,介绍如何构建增量式源代码生成器、使用管道避免重复编译,以及如何持久化状态提高 IDE 响应速度。
UnsafeAccessor:绕过可见性限制的零开销内部访问
介绍 UnsafeAccessorAttribute,如何在无需反射或 unsafe 的情况下访问私有成员,适用于测试、序列化与框架开发。
自定义异步方法构建器:实现非标准状态机(如零分配异步)
通过自定义 AsyncMethodBuilderAttribute 实现完全控制异步状态机,例如没有 Task 分配的异步、合并取消令牌或自定义调度器。
委托链式组合与函数式管道构建
利用多播委托与自定义管道操作符构建可组合的函数链,实现数据流式处理,区别于常规委托事件用法。
不安全上下文中的栈分配Span与零拷贝操作
使用stackalloc在栈上分配内存并通过Span<T>安全操作,结合unsafe指针实现高性能零拷贝数组切片。
自定义可等待类型与关键进度通知机制
实现一个非Task的可等待类型,支持外部取消与分阶段进度报告,打破仅Task可await的常规认知。
静态抽象接口成员实现代数类型系统
利用C# 11静态抽象接口成员模拟代数数据类型(ADT),构建类型安全的表达式求值器。
无锁并发更新不可变集合——基于Interlocked的CAS替换
通过Interlocked.CompareExchange对不可变集合进行原子替换,实现无锁安全并发更新,避免锁竞争。
源码生成器构建属性驱动的状态机框架
通过C# Source Generator根据自定义属性自动生成状态转换代码,消除手写switch-case。
表达式树动态编译实现运行时代码生成与缓存
利用Expression<TDelegate>构建动态方法并编译为委托,结合表达式缓存实现接近原生性能的运行时计算。
零分配约束内存区域——Span+struct实现连续缓冲区
通过栈分配或池化内存结合只读Span与ref struct,构建完全零GC分配的临时缓冲区。
递归模式匹配结合位置析构实现树形数据变换
利用C# 9+的递归模式与位置模式析构,一行代码完成复杂树结构的查询与变换。
异步方法拦截器——注入回调与性能监控的IL操纵
使用Mono.Cecil或Harmony在编译后/运行时修改IL,为任意异步方法添加统计回调,无需改动源码。