source generator 生成的 regex 实例更快,因其绕过运行时编译与缓存查找,直接生成预编译、内联、无反射的静态匹配方法;需满足 sdk、语言版本、常量模式及 regexgenerator 属性三条件才触发;仅支持简单常量模式与 trymatch api,复杂动态表达式或非默认选项不适用。

Source Generator 生成的 Regex 实例为什么更快?
因为绕过了运行时编译(RegexOptions.Compiled 的 JIT 开销)和缓存查找(Regex.Cache 的哈希/锁竞争),直接生成预编译、内联、无反射的匹配方法。它把正则逻辑“翻译”成纯 C# 方法,像手写一样执行。
关键点:
– 不依赖 Regex 类的通用解析路径
– 没有 RegexRunner 抽象层和状态机跳转
– 字符串遍历、分支判断全在生成的 static bool TryMatch(...) 中展开
如何用 RegexGenerator 属性触发源生成?
必须同时满足三个条件,否则生成器静默跳过:
- 项目 SDK 为
Microsoft.NET.Sdk(.NET 6+),且启用源生成:确保<langversion>12.0</langversion>或更高 - 正则模式是编译期常量(
const string或字面量),不能是变量拼接或运行时读取 - 类上标注
[RegexGenerator],且目标方法是static、返回bool、参数至少含ReadOnlySpan<char></char>或string
示例:
[RegexGenerator(@"d{3}-d{2}-d{4}")]
public static partial bool TryParseSsn(ReadOnlySpan<char> input);</char>
生成器会输出一个同名 TryParseSsn 实现 —— 你不用写函数体,也不能写。
生成代码里实际长什么样?
以 @"a(b|c)d" 为例,生成器产出的是展开的字符比较逻辑,类似手写状态机:
if (input.Length <p>真正生成的代码更精细(处理 Unicode、边界、分组捕获等),但核心是:<br>– 所有分支提前折叠(常量传播 + 模式分析)<br>– 捕获组转为 <code>out Range</code> 参数,不分配 <code>GroupCollection</code><br>– 无正则引擎调度开销,调用即执行</p><h3>哪些场景下 <code>RegexGenerator</code> 反而更慢或不可用?</h3><p>不是所有正则都适合源生成:</p>
- 模式含动态部分(如
$"{prefix}\d+")→ 编译失败,提示“pattern must be a compile-time constant” - 使用了
RegexOptions.RightToLeft或RegexOptions.CultureInvariant等非默认选项 → 当前(.NET 8)不支持,会被忽略或报错 - 超长复杂表达式(如嵌套量词 >5 层、回溯风险高)→ 生成器可能卡住或输出低效代码(未做深度优化)
- 需要
Match/Matches返回完整结果对象 → 源生成只支持TryMatch风格 API,捕获需显式声明out参数
真正省下的不是“毫秒”,而是高并发下避免 Regex.Cache 锁争用和 JIT 编译抖动 —— 这点容易被基准测试忽略。











