让我来说明一下,然后,如果您愿意,您可以撕碎我。
正则表达式不是解决此问题的方法-相对而言,它太慢且占用内存。
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();
}