내가 사건을 제기하면 원한다면 조각을 찢을 수 있습니다.
Regex는이 문제에 대한 답이 아닙니다. 너무 느리고 메모리가 부족하여 상대적으로 말하십시오.
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();
}