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 ได้