先让我解释清楚,然后你可以把我撕成碎片。
Regex并不是这个问题的答案——相对来说,它太慢,内存太大。
StringBuilder比string mangling好得多。
因为这将是一个补充字符串的扩展方法。Replace,我认为匹配它的工作方式很重要——因此,对于相同的参数问题抛出异常非常重要,因为如果没有进行替换,则返回原始字符串。
我认为使用StringComparison参数不是一个好主意。
我确实尝试过,但michael-liu最初提到的测试用例显示了一个问题:-
[TestCase("œ", "oe", "", StringComparison.InvariantCultureIgnoreCase, Result = "")]
虽然IndexOf会匹配,但源字符串(1)和oldValue的匹配长度不匹配。长度(2).这通过在一些其他解决方案中导致IndexOutOfRange来体现。长度被添加到当前的匹配位置,我找不到绕过这个方法。
Regex无论如何都无法匹配这种情况,所以我采取了只使用StringComparison的实用解决方案。OrdinalIgnoreCase为我的解决方案。
我的代码类似于其他答案,但我的扭曲是,我在创建StringBuilder之前寻找匹配。如果没有发现,则避免潜在的大分配。然后代码就变成了do{…}while而不是a 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();
}