BrandGhost
C# Regex Patterns for Validation: Email, URL, Phone, and Common Inputs

C# Regex Patterns for Validation: Email, URL, Phone, and Common Inputs

C# Regex Patterns for Validation: Email, URL, Phone, and Common Inputs

C# regex patterns for validation are everywhere -- in login forms, API endpoints, configuration parsers, and data pipelines. Getting them right matters for correctness, security, and performance. Use a pattern that's too loose and you accept garbage input. Use one that's too strict and you reject valid data. Use one without a timeout and you open yourself to ReDoS attacks.

This article provides production-ready patterns for the most common validation scenarios -- email addresses, phone numbers, URLs, postal codes, IP addresses, and more -- using [GeneratedRegex] with timeouts, with guidance on when to use RegexOptions.NonBacktracking for user-facing inputs.


Principles for Production Regex Validation

Applying C# regex for input validation in production requires more than just a working pattern. Performance, security, and maintainability all matter. A pattern that works correctly in a unit test can still cause a production outage if it's not protected against adversarial input. Before diving into specific patterns, here are the guiding principles that should inform every validation regex you write:

  1. Always set a timeout -- user-supplied input combined with complex patterns is a ReDoS risk. Use matchTimeoutMilliseconds in [GeneratedRegex].
  2. Use [GeneratedRegex] for hot paths -- validation is called constantly. Compile-time source generation gives zero startup cost.
  3. Consider NonBacktracking for user-facing patterns -- for patterns without lookaheads/lookbehinds, it provides O(n) linear-time safety.
  4. Don't over-validate -- perfect email validation requires a full RFC 5321 parser. For most use cases, "good enough" patterns that reject obvious garbage are better than patterns so complex they themselves become security risks.
  5. Return meaningful results -- a bool tells you whether it's valid, but not why it failed. Consider returning a discriminated union or error message for user-facing validation.

Setting Up Validation Patterns

The recommended structure for regex validation in .NET is a static partial class with [GeneratedRegex] methods -- one method per pattern. This centralizes all patterns in one file, makes them easy to discover, and ensures each pattern is compiled once at startup rather than re-parsed on every call. Centralize your patterns in a partial static class with [GeneratedRegex] methods:

using System.Text.RegularExpressions;

namespace MyApp.Validation;

public static partial class InputPatterns
{
    // Email -- RFC 5321-ish, practical for most applications
    [GeneratedRegex(
        @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex Email();

    // Phone -- E.164 international format
    [GeneratedRegex(
        @"^+?[1-9]d{1,14}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex PhoneE164();

    // URL -- http/https/ftp
    [GeneratedRegex(
        @"^(https?|ftp)://[^s/$.?#].[^s]*$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex Url();

    // IPv4 address
    [GeneratedRegex(
        @"^((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex IPv4();

    // US ZIP code (5 digit or ZIP+4)
    [GeneratedRegex(
        @"^d{5}(?:-d{4})?$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex UsZipCode();

    // UK Postcode
    [GeneratedRegex(
        @"^[A-Z]{1,2}d[A-Zd]?s*d[A-Z]{2}$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex UkPostcode();
}

Email Validation

Email is notoriously difficult to validate perfectly. RFC 5321 allows formats that look unusual to most users. The practical approach: reject obvious garbage, accept anything that has [email protected] structure.

public static partial class InputPatterns
{
    // Practical email validation -- covers 99%+ of real email addresses
    [GeneratedRegex(
        @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex Email();

    // More permissive -- allows unicode local parts (use for international applications)
    [GeneratedRegex(
        @"^[^@s]+@[^@s]+.[^@s]+$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex EmailPermissive();
}

public static class EmailValidator
{
    public static ValidationResult Validate(string? email)
    {
        if (string.IsNullOrWhiteSpace(email))
            return ValidationResult.Fail("Email address is required.");

        if (email.Length > 254) // RFC 5321 maximum
            return ValidationResult.Fail("Email address is too long.");

        try
        {
            return InputPatterns.Email().IsMatch(email)
                ? ValidationResult.Ok()
                : ValidationResult.Fail("Email address format is invalid.");
        }
        catch (RegexMatchTimeoutException)
        {
            return ValidationResult.Fail("Validation timed out -- input may be malformed.");
        }
    }
}

public sealed record ValidationResult(bool IsValid, string? Error)
{
    public static ValidationResult Ok() => new(true, null);
    public static ValidationResult Fail(string error) => new(false, error);
}

What the Email Pattern Does

Breaking down ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$:

  • ^ -- start of string
  • [a-zA-Z0-9._%+-]+ -- local part: alphanumerics, dots, underscores, percent, plus, hyphen
  • @ -- literal at sign
  • [a-zA-Z0-9.-]+ -- domain: alphanumerics, dots, hyphens
  • . -- literal dot
  • [a-zA-Z]{2,} -- TLD: at least 2 letters
  • $ -- end of string

What it doesn't handle: quoted local parts ("john doe"@example.com), IP address domains (user@[192.168.1.1]), internationalized email. These are edge cases most applications never encounter.


Phone Number Validation

Phone number formats vary enormously by country. The pragmatic approach is to validate one of a few well-defined formats:

public static partial class PhonePatterns
{
    // E.164 international format: +12025551234
    [GeneratedRegex(
        @"^+[1-9]d{1,14}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex E164();

    // US/Canada format: various common representations
    [GeneratedRegex(
        @"^(+1s?)?((?d{3})?[s.-]?)?d{3}[s.-]?d{4}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex NorthAmerica();

    // Generic: just digits, optional +, spaces, hyphens (loose validation)
    [GeneratedRegex(
        @"^+?[ds-()]{7,20}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex Generic();
}

For production phone validation, consider using a library like libphonenumber-csharp which understands country-specific formatting rules and can normalize numbers to E.164 format.

Normalizing Phone Numbers

Before validating a phone number, normalizing it to a canonical form reduces the number of distinct patterns you need to handle. This two-step approach -- strip formatting, then validate -- is more robust than trying to match every possible formatted variation in a single pattern:

[GeneratedRegex(@"[^d+]", RegexOptions.None, matchTimeoutMilliseconds: 200)]
private static partial Regex NonDigitNonPlus();

public static string NormalizePhone(string phone)
{
    // Remove everything except digits and leading +
    var normalized = NonDigitNonPlus().Replace(phone, "");

    // Ensure + only appears at the start
    if (normalized.Contains('+') && !normalized.StartsWith('+'))
        normalized = normalized.Replace("+", "");

    return normalized;
}

// "  (555) 123-4567  " -> "5551234567"
// "+1 (555) 123-4567" -> "+15551234567"

URL Validation

URLs have complex structure. The regex approach works for common http/https/ftp URLs:

public static partial class UrlPatterns
{
    // Practical URL validation
    [GeneratedRegex(
        @"^(https?|ftp)://(?:[a-zA-Z0-9-]+.)+[a-zA-Z]{2,}(?::d{1,5})?(?:/[^s]*)?$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex HttpUrl();

    // More lenient -- allows IP addresses, localhost
    [GeneratedRegex(
        @"^(https?|ftp)://[^s/$.?#].[^s]*$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex AnyUrl();
}

For more robust URL validation, use Uri.TryCreate alongside regex:

public static bool IsValidHttpUrl(string? url)
{
    if (string.IsNullOrWhiteSpace(url)) return false;

    // Let .NET's URI parser handle the complex cases
    if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
        return false;

    return uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps;
}

This hybrid approach is often better than pure regex for URLs -- Uri.TryCreate handles encoding, international domain names, and edge cases that regex struggles with.


IP Address Validation

IP address validation is one of those cases where regex and the built-in System.Net.IPAddress parser overlap, and the right choice depends on context. Regex lets you reject structurally invalid strings before parsing -- useful for fast pre-validation or when you need to extract IP addresses from a larger text. The built-in parser is more authoritative for determining semantic validity. Both approaches are shown here.

IPv4

[GeneratedRegex(
    @"^((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)$",
    RegexOptions.None,
    matchTimeoutMilliseconds: 300)]
public static partial Regex IPv4();

Breaking this down:

  • 25[0-5] -- matches 250-255
  • 2[0-4]d -- matches 200-249
  • [01]?dd? -- matches 0-199

The pattern repeats 4 times with dot separators.

Again, IPAddress.TryParse is often cleaner:

public static bool IsValidIPv4(string? input)
{
    if (string.IsNullOrWhiteSpace(input)) return false;
    return System.Net.IPAddress.TryParse(input, out var addr)
        && addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork;
}

IPv6 (Use Built-in Parser)

IPv6 validation by regex is impractical -- the pattern handles full form, compressed form, and IPv4-mapped addresses. Always use IPAddress.TryParse for IPv6.


Postal Code Validation

Postal code validation is inherently locale-specific. Each country has its own format, length, and character set rules. The practical approach is a static class with one method per country code, so callers select the right validator explicitly rather than trying to auto-detect format. The patterns below cover the most common cases for North American and European addresses:

public static partial class PostalPatterns
{
    // US ZIP code: 5 digits or ZIP+4
    [GeneratedRegex(@"^d{5}(?:-d{4})?$", RegexOptions.None, matchTimeoutMilliseconds: 200)]
    public static partial Regex UsZip();

    // Canadian postal code: A1A 1A1 (with or without space)
    [GeneratedRegex(
        @"^[ABCEGHJ-NPRSTVXY]d[ABCEGHJ-NPRSTV-Z]s?d[ABCEGHJ-NPRSTV-Z]d$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex CanadianPostal();

    // UK postcode
    [GeneratedRegex(
        @"^[A-Z]{1,2}d[A-Zd]?s*d[A-Z]{2}$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex UkPostcode();
}

Credit Card Number Validation (Structure Only)

Important: Never validate credit card numbers in your own code for actual payment processing -- use a PCI DSS-compliant payment processor. This pattern only validates structural format:

public static partial class PaymentPatterns
{
    // Generic card number: 13-19 digits, optional spaces/hyphens every 4
    [GeneratedRegex(
        @"^(d{4}[s-]?){3}d{4,7}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex CardNumberFormat();

    // Luhn check is required for real validation -- this is structure only
    public static bool PassesLuhn(string number)
    {
        var digits = number.Where(char.IsDigit).Select(c => c - '0').ToArray();
        int sum = 0;
        bool alternate = false;
        for (int i = digits.Length - 1; i >= 0; i--)
        {
            int n = digits[i];
            if (alternate)
            {
                n *= 2;
                if (n > 9) n -= 9;
            }
            sum += n;
            alternate = !alternate;
        }
        return sum % 10 == 0;
    }
}

Strong Password Validation

Password complexity requirements vary by application. Here's a configurable approach:

public static partial class PasswordPatterns
{
    // Requires: 8+ chars, uppercase, lowercase, digit, special char
    [GeneratedRegex(
        @"^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[!@#$%^&*()-_=+[]{};:'"",.<>?/\|`~]).{8,128}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex StrongPassword();

    // Minimum 12 chars, any character combination (passphrase-friendly)
    [GeneratedRegex(@"^.{12,128}$", RegexOptions.None, matchTimeoutMilliseconds: 100)]
    public static partial Regex PassphraseLength();
}

public static class PasswordValidator
{
    public static IReadOnlyList<string> Validate(string password)
    {
        var errors = new List<string>();

        if (password.Length < 8)
            errors.Add("Password must be at least 8 characters.");

        if (!password.Any(char.IsUpper))
            errors.Add("Password must contain at least one uppercase letter.");

        if (!password.Any(char.IsLower))
            errors.Add("Password must contain at least one lowercase letter.");

        if (!password.Any(char.IsDigit))
            errors.Add("Password must contain at least one digit.");

        return errors;
    }
}

Note: for the strong password pattern with multiple lookaheads, you'll need [GeneratedRegex] or Compiled mode -- NonBacktracking doesn't support lookaheads.


Building a Reusable Validation Service

For applications that validate many input types, a service class with injected validators is cleaner than scattered static calls. This pairs naturally with feature slicing in C# -- each feature slice registers its own validators:

public interface IInputValidator
{
    ValidationResult Validate(string? input);
}

public sealed class RegexValidator : IInputValidator
{
    private readonly Regex _regex;
    private readonly string _errorMessage;

    public RegexValidator(Regex regex, string errorMessage)
    {
        _regex = regex;
        _errorMessage = errorMessage;
    }

    public ValidationResult Validate(string? input)
    {
        if (string.IsNullOrWhiteSpace(input))
            return ValidationResult.Fail("Input is required.");

        try
        {
            return _regex.IsMatch(input)
                ? ValidationResult.Ok()
                : ValidationResult.Fail(_errorMessage);
        }
        catch (RegexMatchTimeoutException)
        {
            return ValidationResult.Fail("Validation timeout.");
        }
    }
}

For extensible validation in plugin-based architectures, each plugin can contribute its own IInputValidator instances. The host application doesn't need to know the specific patterns -- it just calls Validate on each registered validator.

The Singleton Design Pattern in C# is relevant here -- your validator instances are typically singletons registered in the DI container, ensuring the [GeneratedRegex]-backed instances are shared.


Using NonBacktracking for Security-Critical Validation

When validation runs against user-supplied input, ReDoS (Regular Expression Denial of Service) is a genuine threat. An attacker can craft an input that causes the engine to backtrack exponentially, consuming 100% CPU and hanging the server. For patterns that don't require lookaheads or lookbehinds, RegexOptions.NonBacktracking eliminates this risk entirely. It uses a different engine algorithm that guarantees O(n) time regardless of input content. Combine it with a timeout as a belt-and-suspenders defense:

// NonBacktracking + timeout: double defense for user input
var safeEmailValidator = new Regex(
    @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$",
    RegexOptions.NonBacktracking | RegexOptions.IgnoreCase,
    matchTimeout: TimeSpan.FromMilliseconds(500));

Note that NonBacktracking can be combined with RegexOptions.IgnoreCase and most other options, just not with lookahead/lookbehind patterns.


Enum-Style Validation Categories

When you have multiple validators and need to select between them, consider modeling validation rules as an enum-style discriminated union. C# Enum to String: Conversion Patterns and Best Practices covers the techniques for making enum values human-readable -- useful when displaying validation rule names in error messages.


Complete Validation Module Example

The following brings all the individual validators together into a single, feature-organized module. This is the structure recommended for production use: all patterns in one static partial class, each with a timeout, organized by input domain. Here's how all the pieces fit together in a feature-organized module:

namespace MyApp.Users.Validation;

public static partial class UserInputPatterns
{
    [GeneratedRegex(
        @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$",
        RegexOptions.IgnoreCase,
        matchTimeoutMilliseconds: 500)]
    public static partial Regex Email();

    [GeneratedRegex(
        @"^[a-zA-Z][a-zA-Z0-9_-]{2,29}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex Username();

    [GeneratedRegex(
        @"^+?[1-9]d{1,14}$",
        RegexOptions.None,
        matchTimeoutMilliseconds: 200)]
    public static partial Regex PhoneE164();
}

public sealed class UserRegistrationValidator
{
    public IReadOnlyList<string> Validate(UserRegistrationRequest request)
    {
        var errors = new List<string>();

        ValidateField(errors, request.Email, UserInputPatterns.Email(),
            "Email address format is invalid.");

        ValidateField(errors, request.Username, UserInputPatterns.Username(),
            "Username must be 3-30 characters: letters, digits, hyphens, underscores only.");

        if (!string.IsNullOrEmpty(request.Phone))
        {
            ValidateField(errors, request.Phone, UserInputPatterns.PhoneE164(),
                "Phone must be in E.164 format (+12025551234).");
        }

        return errors;
    }

    private static void ValidateField(
        List<string> errors,
        string? value,
        Regex pattern,
        string errorMessage)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            errors.Add($"Field is required.");
            return;
        }

        try
        {
            if (!pattern.IsMatch(value))
                errors.Add(errorMessage);
        }
        catch (RegexMatchTimeoutException)
        {
            errors.Add("Validation timeout -- please check your input.");
        }
    }
}

public sealed record UserRegistrationRequest(
    string? Email,
    string? Username,
    string? Phone);


Testing Your Validation Patterns

Regex validation patterns need tests that cover more than the happy path. A pattern that correctly accepts valid input but fails to reject clever malicious input is dangerous in security-sensitive contexts. A pattern that rejects valid but unusual input causes user frustration. Both failure modes cost you trust.

The minimum test set for any validation pattern:

Happy path inputs: Standard valid forms the pattern must accept. For email: [email protected], [email protected]. For US phone: (555) 123-4567, 555-123-4567, 5551234567.

Edge cases within the valid set: Minimum-length valid inputs, maximum-length valid inputs, inputs with all allowed special characters, inputs where optional components are present vs absent.

Invalid inputs that should be rejected: Completely wrong format, missing required components, extra characters before ^ or after $ if not anchored, SQL injection patterns, XSS patterns, format-correct but semantically invalid (like a date of February 30th for date validators).

Near-miss inputs: Inputs one character away from valid -- a single character too many, too few, or of the wrong type. These find off-by-one errors in quantifiers.

Adversarial inputs: For patterns that accept user input, include inputs designed to trigger catastrophic backtracking. A string of 30+ repeated characters followed by a character that can't match is the classic test. With a timeout set, the test should throw RegexMatchTimeoutException rather than hanging.

Here's a structured test class example using xUnit:

public class EmailValidationTests
{
    [Theory]
    [InlineData("[email protected]", true)]
    [InlineData("[email protected]", true)]
    [InlineData("user@[192.168.1.1]", false)]   // IP literals not accepted by simplified pattern
    [InlineData("@nodomain.com", false)]
    [InlineData("nodomain@", false)]
    [InlineData("two@@at.com", false)]
    [InlineData("", false)]
    [InlineData("   ", false)]
    public void EmailPattern_ValidatesCorrectly(string input, bool expected)
    {
        bool result = UserInputPatterns.Email().IsMatch(input);
        Assert.Equal(expected, result);
    }
}

Parameterized tests with InlineData make it easy to add new test cases as you discover edge cases in production. Keep the test data growing over time -- every production bug should result in a new test case.


Performance Considerations for Validation

Validation patterns are often called on every incoming request. For a web API processing thousands of requests per second, the regex overhead can be meaningful -- but context determines whether optimization is necessary.

[GeneratedRegex] with a timeout is the right choice for production validators. The generated code runs faster than both interpreted and Compiled modes. With a timeout of 100-500ms, you get safety against adversarial input with minimal overhead on legitimate input.

RegexOptions.NonBacktracking is appropriate for validators where the pattern doesn't use lookaheads or backreferences. Email validation, phone validation, and most simple format validators can be written without these constructs. NonBacktracking guarantees O(n) time regardless of input, making it truly immune to ReDoS rather than just having a safety timeout:

// Email validator without lookaheads -- safe for NonBacktracking
[GeneratedRegex(
    @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$",
    RegexOptions.NonBacktracking,
    matchTimeoutMilliseconds: 100)]
private static partial Regex SafeEmailPattern();

Password strength validators with multiple (?=.*) lookaheads CANNOT use NonBacktracking. For those, rely on the timeout, and consider breaking the strength check into multiple simpler IsMatch calls rather than one complex pattern -- this is often faster and easier to maintain.

For validators that run at high volume, benchmark your actual workload with BenchmarkDotNet before deciding the regex approach needs optimization. String allocation from the regex match is usually not the bottleneck. The bottleneck is more often the network I/O or database query that surrounds the validation.


FAQ

What is the best regex for email validation in C#?

For most applications: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$ with RegexOptions.IgnoreCase. Wrap it in [GeneratedRegex] with a timeout. This accepts virtually all real-world email addresses while rejecting obvious garbage. Full RFC 5321 compliance requires a proper parser -- don't attempt it with regex.

How do I validate a phone number in C#?

For international numbers in E.164 format: ^+?[1-9]d{1,14}$. For US/Canada flexible formatting: ^(+1s?)?((?d{3})?[s.-]?)?d{3}[s.-]?d{4}$. For maximum correctness, use the libphonenumber-csharp library. Normalize to E.164 before storing.

How do I validate a URL in C# -- regex or Uri.TryCreate?

Both. Use Uri.TryCreate as the primary check for structural validity, then optionally check uri.Scheme for allowed protocols. Regex is useful for additional constraints (e.g., no IP-only URLs, required HTTPS). The hybrid approach handles encoding, international domains, and edge cases that regex struggles with.

Should I use NonBacktracking for validation regex?

Yes, for patterns applied to user-supplied data that don't need lookaheads or backreferences. NonBacktracking provides O(n) linear-time matching and is immune to catastrophic backtracking. The email, phone, and postal code patterns in this article are all compatible with NonBacktracking.

How do I prevent ReDoS in my C# validation code?

Two complementary approaches: 1) Use matchTimeoutMilliseconds in [GeneratedRegex] (or the matchTimeout constructor parameter) so the engine throws RegexMatchTimeoutException instead of hanging. 2) Use RegexOptions.NonBacktracking for patterns that don't need lookaheads -- it's mathematically immune to catastrophic backtracking.

Is there a C# regex for credit card validation?

Regex can validate the structural format (digit groupings, length) but not card validity. Use the Luhn algorithm to check validity. For actual payment processing, always use a PCI DSS-compliant processor like Stripe or Braintree -- never process or store raw card numbers yourself.

How do I organize many validation regex patterns in C#?

Use [GeneratedRegex] in a partial static class, grouped by domain (e.g., UserInputPatterns, PaymentPatterns, AddressPatterns). This keeps patterns centralized, enables compile-time optimization, and makes it easy to find and update patterns. Pair with feature slicing so each module owns its relevant validators.

C# Regex: Complete Guide to Regular Expressions in .NET

Master C# Regex with this complete guide covering pattern syntax, RegexOptions, GeneratedRegex, performance, and real .NET code examples.

Regex Options in C#: A Beginner's Guide to Powerful Pattern Matching

Regular expressions are powerful for pattern matching, but what are the regex options in C# that we have access to? What do they do and how can we use them?

C# Regex Performance: How To Squeeze Out Performance

Regular expressions are powerful for pattern matching, but what about performance? Check out this article for details on C# regex performance from benchmarks!

An error has occurred. This application may no longer respond until reloaded. Reload