ให้ฉันทำกรณีของฉันแล้วคุณสามารถฉีกฉันเป็นชิ้นเล็กชิ้นน้อยถ้าคุณต้องการ
Regex ไม่ใช่คำตอบสำหรับปัญหานี้ - ช้าเกินไปและหน่วยความจำกำลังหิว
StringBuilder ดีกว่า mangling สตริงมาก
เนื่องจากนี่จะเป็นวิธีส่วนขยายในการเสริมstring.Replace
ผมเชื่อว่ามันสำคัญที่จะต้องจับคู่วิธีการทำงานดังนั้นการทิ้งข้อยกเว้นสำหรับปัญหาอาร์กิวเมนต์เดียวกันจึงมีความสำคัญเช่นเดียวกับการส่งคืนสตริงต้นฉบับหากไม่มีการแทนที่
ฉันเชื่อว่าการมีพารามิเตอร์ StringComparison ไม่ใช่ความคิดที่ดี ฉันลองแล้ว แต่กรณีทดสอบที่กล่าวถึงโดย michael-liu พบว่ามีปัญหา: -
[TestCase("œ", "oe", "", StringComparison.InvariantCultureIgnoreCase, Result = "")]
ขณะที่ IndexOf จะจับคู่กันจะมีความไม่ตรงกันระหว่างความยาวของการจับคู่ในสตริงต้นทาง (1) และ oldValue.Length (2) สิ่งนี้ประจักษ์เองโดยทำให้ IndexOutOfRange ในโซลูชันอื่น ๆ เมื่อ oldValue.Length ถูกเพิ่มเข้ากับตำแหน่งการแข่งขันปัจจุบันและฉันไม่สามารถหาวิธีแก้ไขปัญหานี้ได้ Regex ไม่สามารถจับคู่เคสได้ดังนั้นฉันจึงใช้วิธีแก้ปัญหาอย่างจริงจังในการใช้StringComparison.OrdinalIgnoreCase
สำหรับโซลูชันของฉันเท่านั้น
รหัสของฉันคือคล้ายกับคำตอบอื่น ๆ StringBuilder
แต่บิดของฉันเป็นที่ฉันมองหาการแข่งขันก่อนที่จะไปสู่ปัญหาของการสร้างที่ หากไม่พบสิ่งใดแสดงว่ามีการหลีกเลี่ยงการจัดสรรที่มีขนาดใหญ่ รหัสจะกลายเป็นdo{...}while
มากกว่าwhile{...}
ฉันได้ทำการทดสอบอย่างครอบคลุมกับ Answers อื่น ๆ และสิ่งนี้ออกมาเร็วกว่าเล็กน้อยและใช้หน่วยความจำน้อยลงเล็กน้อย
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();
}