Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

ตัวเลือกแทน String.Replace แบบ Case-Insensitive ใน C#

String.Replace เป็น Case-Sensitive เท่านั้น หากต้องการ Replace แบบไม่สนใจ Case (Case-Insensitive) ต้องใช้วิธีอื่น

วิธีที่ 1: Regex.Replace (มาตรฐาน ที่สุด)

using System.Text.RegularExpressions;

public static string ReplaceCaseInsensitive(string input, string oldValue, string newValue)
{
    if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(oldValue))
        return input;
    
    // Regex.Escape เพื่อจัดการ Special Characters ใน oldValue
    string pattern = Regex.Escape(oldValue);
    return Regex.Replace(input, pattern, newValue, RegexOptions.IgnoreCase);
}

// ใช้งาน
string text = "Cricket Team";
string result = ReplaceCaseInsensitive(text, "t", "b");
Console.WriteLine(result); // "Crickeb beam" (t และ T ทั้งคู่ถูกแทนที่)

วิธีที่ 2: StringBuilder + IndexOf (Manual, ไม่ใช้ Regex)

public static string ReplaceCaseInsensitiveManual(string input, string oldValue, string newValue)
{
    if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(oldValue))
        return input;
    
    var sb = new StringBuilder();
    int startIndex = 0;
    int matchIndex;
    
    while ((matchIndex = input.IndexOf(oldValue, startIndex, StringComparison.OrdinalIgnoreCase)) >= 0)
    {
        // Append ส่วนก่อน Match
        sb.Append(input, startIndex, matchIndex - startIndex);
        // Append Replacement
        sb.Append(newValue);
        // Move Index
        startIndex = matchIndex + oldValue.Length;
    }
    
    // Append ส่วนท้าย
    sb.Append(input, startIndex, input.Length - startIndex);
    return sb.ToString();
}

วิธีที่ 3: LINQ + StringBuilder (Functional Style)

public static string ReplaceCaseInsensitiveLinq(string input, string oldValue, string newValue)
{
    if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(oldValue))
        return input;
    
    return string.Join(newValue, 
        Regex.Split(input, Regex.Escape(oldValue), RegexOptions.IgnoreCase));
}
// หมายเหตุ: Regex.Split คืน Array ของ Substrings ระหว่าง Matches

Benchmark Comparison

// ใช้ BenchmarkDotNet
// Input: 10KB String, Replace "the" -> "THE" (Case-insensitive)
// Results (Approximate):
// String.Replace (Case-Sensitive):     ~5 μs
// Regex.Replace (IgnoreCase):          ~15 μs
// Manual IndexOf + StringBuilder:      ~8 μs
// Regex.Split + Join:                  ~20 μs

ตัวอย่างครบถ้วน

static void Main()
{
    string original = "Cricket Team cricket TEAM";
    string oldVal = "team";
    string newVal = "SQUAD";
    
    Console.WriteLine($"Original: {original}");
    Console.WriteLine($"Regex:    {ReplaceCaseInsensitive(original, oldVal, newVal)}");
    Console.WriteLine($"Manual:   {ReplaceCaseInsensitiveManual(original, oldVal, newVal)}");
    Console.WriteLine($"LINQ:     {ReplaceCaseInsensitiveLinq(original, oldVal, newVal)}");
}

ผลลัพธ์

Original: Cricket Team cricket TEAM
Regex:    Cricket SQUAD cricket SQUAD
Manual:   Cricket SQUAD cricket SQUAD
LINQ:     Cricket SQUAD cricket SQUAD

ข้อควรระวัง

  • Regex.Escape: จำเป็นต้อง Escape Special Characters (. * + ? ^ $ { } [ ] \ | ( ) ) ใน oldValue
  • Culture: StringComparison.OrdinalIgnoreCase เร็วกว่า CurrentCultureIgnoreCase และ Consistent
  • Overlapping Matches: Regex ไม่จับ Overlapping (เช่น "aaa" Replace "aa" -> "b" ได้ "ba" ไม่ใช่ "bb")
  • Performance: สำหรับ String เล็ก/เรียกน้อย Regex OK สำหรับ Hot Path ใช้ Manual/IndexOf

ใน .NET 7+ มี Built-in?

ยังไม่มี Built-in Method ตรงๆ แต่สามารถใช้ MemoryExtensions.Replace (Span-based) ร่วมกับ Custom Logic ได้