Biarkan saya membuat kasing saya dan kemudian Anda dapat mencabik-cabik saya jika Anda mau.
Regex bukan jawaban untuk masalah ini - terlalu lambat dan memori haus, relatif berbicara.
StringBuilder jauh lebih baik daripada string mangling.
Karena ini akan menjadi metode ekstensi untuk melengkapi string.Replace
, saya percaya penting untuk mencocokkan cara kerjanya - karena itu melempar pengecualian untuk masalah argumen yang sama adalah penting seperti mengembalikan string asli jika penggantian tidak dilakukan.
Saya percaya bahwa memiliki parameter StringComparison bukanlah ide yang baik. Saya memang mencobanya tetapi test case yang awalnya disebutkan oleh michael-liu menunjukkan masalah: -
[TestCase("œ", "oe", "", StringComparison.InvariantCultureIgnoreCase, Result = "")]
Sementara IndexOf akan cocok, ada ketidakcocokan antara panjang pertandingan dalam string sumber (1) dan oldValue.Length (2). Ini memanifestasikan dirinya dengan menyebabkan IndexOutOfRange dalam beberapa solusi lain ketika oldValue.Length ditambahkan ke posisi pertandingan saat ini dan saya tidak dapat menemukan cara untuk mengatasi ini. Lagipula Regex gagal untuk mencocokkan case, jadi saya mengambil solusi pragmatis dari hanya menggunakan StringComparison.OrdinalIgnoreCase
untuk solusi saya.
Kode saya mirip dengan jawaban lain tetapi putaran saya adalah bahwa saya mencari kecocokan sebelum kesulitan membuat StringBuilder
. Jika tidak ada yang ditemukan maka alokasi yang berpotensi besar dihindari. Kode kemudian menjadi a do{...}while
daripada awhile{...}
Saya telah melakukan beberapa pengujian ekstensif terhadap Jawaban lain dan ini keluar lebih cepat dan menggunakan sedikit memori.
public static string ReplaceCaseInsensitive(this string str, string oldValue, string newValue)
{
if (str == null) throw new ArgumentNullException(nameof(str));
if (oldValue == null) throw new ArgumentNullException(nameof(oldValue));
if (oldValue.Length == 0) throw new ArgumentException("String cannot be of zero length.", nameof(oldValue));
var position = str.IndexOf(oldValue, 0, StringComparison.OrdinalIgnoreCase);
if (position == -1) return str;
var sb = new StringBuilder(str.Length);
var lastPosition = 0;
do
{
sb.Append(str, lastPosition, position - lastPosition);
sb.Append(newValue);
} while ((position = str.IndexOf(oldValue, lastPosition = position + oldValue.Length, StringComparison.OrdinalIgnoreCase)) != -1);
sb.Append(str, lastPosition, str.Length - lastPosition);
return sb.ToString();
}