Skip to content

fix: anchor Email regex to prevent substring matching & perf: optimize RemoveCharacters via SearchValues - #12

Open
sdwck wants to merge 2 commits into
Antyss77:masterfrom
sdwck:master
Open

fix: anchor Email regex to prevent substring matching & perf: optimize RemoveCharacters via SearchValues#12
sdwck wants to merge 2 commits into
Antyss77:masterfrom
sdwck:master

Conversation

@sdwck

@sdwck sdwck commented Aug 10, 2026

Copy link
Copy Markdown

Hey! Saw your project on Reddit. Really love the focus on zero-allocation.

I made a couple of improvements:

  • The email regex wasn't anchored, meaning it could incorrectly match invalid emails if a valid one was just a substring. I added anchors to fix this.
  • I noticed RemoveCharacters uses .IndexOf() inside the loop, so I optimized it using System.Buffers.SearchValues (makes character lookup practically O(1)).

Benchmark Results

Method Mean Error StdDev Ratio RatioSD Allocated Alloc Ratio
RemoveCharacters_CharArray 33.41 ns 0.317 ns 0.296 ns 1.00 0.01 40 B 1.00
RemoveCharacters_SearchValues 27.72 ns 0.240 ns 0.225 ns 0.83 0.01 40 B 1.00
RemoveCharacters_Long_CharArray 2,730.60 ns 19.030 ns 16.869 ns 81.75 0.85 1624 B 40.60
RemoveCharacters_Long_SearchValues 2,097.94 ns 8.208 ns 7.678 ns 62.81 0.58 1624 B 40.60

Great work on the library, keep it up!

@Antyss77

Copy link
Copy Markdown
Owner

Thanks a lot for this, both changes are genuinely solid.

The regex anchor fix is a real bug catch IsValidEmail was matching an email as a substring anywhere in the string, which isn't what "is this a valid email" should mean. Good tests to go with it too.

The SearchValues optimization is well done, and it follows the existing conventions closely (StackAllocThreshold, ArrayPool/try-finally pattern, XML docs). I traced through the algorithm by hand and it looks correct, including on consecutive matches.

Two small things before merging:

  1. This repo just went through a pass of properly annotating nullable parameters (string?, char[]? etc. wherever a method already guards against null). Your new RemoveCharacters(string, SearchValues<char>) overload checks searchValues is null, but the parameter isn't marked SearchValues<char>? (same for input/string). Could you align it with that, so it's consistent with the rest of the API?
  2. I noticed the BenchmarkRunner.Run<...>BenchmarkSwitcher.FromAssembly(...) change in Benchmark.cs. That's unrelated to the regex/SearchValues fixes was that intentional? If so, could you split it into its own PR so each change stays focused on one thing?

Once those are sorted I'm happy to merge. Thanks again, this is exactly the kind of contribution I was hoping for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants