让我证明我的情况,然后如果你愿意,你可以把我撕成碎片。
正则表达式不是解决这个问题的办法 - 相对来说太慢而且内存占用很大。
StringBuilder 比字符串修饰要好得多。
由于这将是补充string.Replace 的扩展方法,我认为匹配它的工作原理很重要 - 因此对于相同的参数问题抛出异常很重要,如果没有进行替换则返回原始字符串。
我认为拥有 StringComparison 参数不是一个好主意。
我确实尝试过,但michael-liu最初提到的测试用例显示了一个问题:-
[TestCase("œ", "oe", "", StringComparison.InvariantCultureIgnoreCase, Result = "")]
虽然 IndexOf 会匹配,但源字符串 (1) 和 oldValue.Length (2) 中的匹配长度不匹配。当 oldValue.Length 添加到当前匹配位置时,这通过在其他一些解决方案中导致 IndexOutOfRange 表现出来,我找不到解决这个问题的方法。
无论如何,正则表达式都无法匹配案例,所以我采取了只使用StringComparison.OrdinalIgnoreCase 作为我的解决方案的务实解决方案。
我的代码与其他答案相似,但我的转折是在创建StringBuilder 之前先寻找匹配项。如果没有找到,则避免潜在的大分配。然后代码变为do{...}while 而不是while{...}
我已经针对其他答案进行了一些广泛的测试,结果速度快了一点,使用的内存也少了一点。
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();
}