AgentSkillsCN

dotnet-source-gen-regex

将 Regex 实例转换为使用编译时源代码生成器。当用户希望优化正则表达式的性能,或提升其与 AOT 的兼容性时,可选用此方案。

SKILL.md
--- frontmatter
name: dotnet-source-gen-regex
description: Converts Regex instances to use the compile-time source generator. Use when the user wants to optimize regex performance or enable AOT compatibility.
license: MIT
metadata:
  author: Im5tu
  version: "1.0"
  repositoryUrl: https://github.com/im5tu/dotnet-skills
allowed-tools: Bash(dotnet:*) Read Glob Grep AskUserQuestion

.NET Regex Source Generator

The regex source generator creates compile-time generated regex implementations that are:

  • AOT-compatible: Works with Native AOT and trimming
  • Debuggable: Step through the generated matching code
  • Performant: No runtime compilation overhead

When to Use

This skill applies when the user:

  • Wants to optimize regex performance
  • Needs AOT-compatible regex patterns
  • Asks about [GeneratedRegex] attribute
  • Mentions converting new Regex(...) to source-generated
  • Discusses regex compilation or startup performance

Workflow

  1. Find regex usages in the codebase:

    • new Regex(...) constructor calls
    • Regex.IsMatch(), Regex.Match(), Regex.Replace() static method calls
    • Other static Regex.* methods with inline patterns
  2. For each regex with a compile-time known pattern:

    • Ensure the containing class is partial
    • Create a partial method with [GeneratedRegex] attribute:
      csharp
      [GeneratedRegex("pattern", RegexOptions.IgnoreCase)]
      private static partial Regex MyRegex();
      
    • Name the method descriptively based on what the pattern matches
  3. Replace usages to call the generated method:

    csharp
    // Before
    var regex = new Regex(@"\d+", RegexOptions.Compiled);
    if (regex.IsMatch(input)) { ... }
    
    // After
    if (MyNumberRegex().IsMatch(input)) { ... }
    
    [GeneratedRegex(@"\d+")]
    private static partial Regex MyNumberRegex();
    
  4. Verify with dotnet build

  5. If build fails, check:

    • Class is marked partial
    • Pattern is a compile-time constant
    • .NET version is 7 or higher

Key Notes

NoteDetail
RegexOptions.CompiledIgnored by source gen - remove it
.NET VersionRequires .NET 7+
CachingGenerated method caches singleton internally
TimeoutUse [GeneratedRegex("pattern", RegexOptions.None, 1000)] for timeout (milliseconds)

Pattern Conversion Examples

Instance with options:

csharp
// Before
private readonly Regex _emailRegex = new(@"^[\w-\.]+@[\w-]+\.\w+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

// After
[GeneratedRegex(@"^[\w-\.]+@[\w-]+\.\w+$", RegexOptions.IgnoreCase)]
private static partial Regex EmailRegex();

Static method call:

csharp
// Before
if (Regex.IsMatch(input, @"^\d{3}-\d{4}$"))

// After
if (PhoneNumberRegex().IsMatch(input))

[GeneratedRegex(@"^\d{3}-\d{4}$")]
private static partial Regex PhoneNumberRegex();

Error Handling

  • If pattern is not constant: Cannot use source gen - leave as runtime regex
  • If class is not partial: Add partial modifier to the class declaration
  • If build fails after conversion: Check error messages for unsupported pattern features