다음을 통해 공유


String.Trim*(params ReadOnlySpan<char>) 오버로드가 제거됨

.NET 에코시스템에서 다음을 ReadOnlySpan<char> 나타낼 수 있습니다.

  • 특정 문자 시퀀스(대개 큰 System.String 인스턴스의 조각)입니다.
  • 단일 문자의 컬렉션으로, 종종 한 조각 char[]으로 사용됩니다.

.NET 9의 이전 릴리스는 이미 오버로드가 있는 메서드 그룹에 오버로드를 params T[] 추가 params ReadOnlySpan<T> 했습니다. 이 오버로드는 일부 메서드 그룹에 대해 긍정적인 추가이지만 이중 특성 ReadOnlySpan<char> 으로 인해 a 및 a String (동일한 위치)를 수락 char[] 하고 다르게 처리되는 메서드 그룹에 혼동을 일으킬 수 있습니다. 예를 들어 public static string [String::]Split(string separator, StringSplitOptions options) 문자 시퀀스를 하나의 구분 기호로 간주합니다. 예를 들어 . "[]ne]-[Tw[]".Split("]-[", StringSplitOptions.None) new string[] { "[]ne", "Tw[]" }; 반면 public static [String::]Split(char[] separator, StringSplitOptions options) 에 각 문자를 separator 고유 구분 기호로 간주하므로 배열에 해당하는 분할이 생성됩니다 new string[] { "", "", "ne", "", "", "Tw", "", "" }. 따라서 a ReadOnlySpan<char> 를 허용하는 새 오버로드는 문자열과 유사한지 또는 배열과 같은지 결정해야 합니다. 일반적으로 .NET은 배열과 유사한 동작을 준수합니다.

dotnet/runtime#77873에서 제안된 대로 인수를 수락 ReadOnlySpan<char> 하는 다음과 같은 새 String 오버로드를 고려합니다.

public string[] Split(params ReadOnlySpan<char> separator);
public string Trim(params ReadOnlySpan<char> trimChars);
public string TrimStart(params ReadOnlySpan<char> trimChars);
public string TrimEnd(params ReadOnlySpan<char> trimChars);

또한 다음과 같이 일반적으로 정의된 확장 메서드를 고려합니다.

public static class SomeExtensions {
    public static string TrimEnd(this string target, string trimString) {
        if (target.EndsWith(trimString) {
            return target.Substring(0, target.Length - trimString.Length);
        }

        return target;
    }
}

기존 .NET 런타임의 경우 이 확장 메서드는 문자열의 끝에서 지정된 시퀀스를 제거합니다. 그러나 C# "12345!!!!".TrimEnd("!!!") 의 오버로드 확인 규칙으로 인해 기존 확장 메서드에 대한 새 TrimEnd 오버로드를 선호하고 결과를 "12345!" 변경합니다(세 개의 느낌표의 전체 집합만 제거) "12345" 에서 (끝에서 모든 느낌표 제거).

이 중단을 해결하기 위해 두 가지 가능한 경로가 있었습니다. 더 나은 대상인 인스턴스 메서드 public string TrimEnd(string trimString) 를 도입하거나 새 메서드를 제거합니다. 첫 번째 옵션은 대상 문자열의 인스턴스 하나 또는 모두를 반환할지 여부를 결정해야 하므로 추가 위험을 수반합니다. 또한 각 접근 방식을 사용하는 기존 코드를 사용하는 호출자가 의심할 여지 없이 있습니다. 따라서 두 번째 옵션은 릴리스 주기의 이 단계에 가장 적합한 선택이었습니다.

예를 들어 str.Trim(';', ',', '.')기능을 사용하여 params 개별 문자를 전달하는 호출자에게 String.Trim 는 중단이 표시되지 않습니다. 코드가 자동으로 호출 string.Trim(params char[]) string.Trim(params ReadOnlySpan<char>)에서 .로 전환됩니다. .NET 9의 GA 릴리스에 대해 다시 빌드하면 컴파일러가 자동으로 오버로드로 char[] 다시 전환됩니다.

명시적으로 전달 ReadOnlySpan<char> 한 호출자String.Trim(또는 변환char[]할 수 ReadOnlySpan<char> 없는 형식)는 이 변경 후 성공적으로 호출 Trim 되도록 코드를 변경해야 합니다.

String.Split와 달리 String.Trim이 메서드에는 이미 단일 문자열 매개 변수와 새로 추가 ReadOnlySpan<char> 된 오버로드를 허용하는 확장 메서드보다 기본 설정되는 오버로드가 있습니다. 이러한 이유로 새 오버로드가 String.Split 유지되었습니다.

참고 항목

제거된 메서드에 대한 호출이 제거되도록 .NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 또는 .NET 9 RC2에 대해 빌드된 어셈블리를 다시 빌드해야 합니다. 이렇게 하지 않으면 런타임에 MissingMethodException 발생할 수 있습니다.

도입된 버전

.NET 9 GA

이전 동작

.NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 및 .NET 9 RC2에서 컴파일된 다음 코드는 다음과 같습니다.

private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };

// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));

.NET 9 미리 보기 6 이전에는 다음 코드가 생성되었습니다 "prefixinfix". .NET 9 Preview 6~ .NET 9 RC2의 경우 대신 다음을 생성했습니다 "prefixin".

internal static string TrimEnd(this string target, string suffix)
{
    if (target.EndsWith(suffix))
    {
        return target.Substring(0, target.Length - suffix.Length);
    }

    return target;
}

...
return "prefixinfixsuffix".TrimEnd("suffix");

새 동작

배열 조각을 명시적으로 사용하는 다음 코드는 호출하기에 적합한 오버로드가 없으므로 더 이상 컴파일되지 않습니다.

private static readonly char[] s_allowedWhitespace = { ' ', '\t', '\u00A0', '\u2000' };

// Only remove the ASCII whitespace.
str = str.Trim(s_allowedWhitespace.AsSpan(0, 2));

확장 메서드 string TrimEnd(this string target, this string suffix) 를 특징으로 하는 코드는 이제 .NET 8 및 이전 버전에서와 동일한 동작을 했습니다. 즉, 생성됩니다 "prefixinfix".

호환성이 손상되는 변경의 형식

이 변경은 이진 호환성소스 호환성에 영향을 줄 수 있습니다.

변경 이유

많은 프로젝트에는 다시 컴파일한 후 동작이 변경되는 확장 메서드가 있습니다. 이러한 새 인스턴스 메서드의 부정적인 영향은 긍정적인 이점을 능가하는 것으로 간주되었습니다.

.NET 9 Preview 6, .NET 9 Preview 7, .NET 9 RC1 또는 .NET 9 RC2에 대해 빌드된 모든 프로젝트를 다시 컴파일합니다. 프로젝트가 오류 없이 컴파일되는 경우 추가 작업이 필요하지 않습니다. 프로젝트가 더 이상 컴파일되지 않으면 코드를 조정합니다. 가능한 대체 예제 중 하나는 다음과 같습니다.

-private static ReadOnlySpan<char> s_trimChars = [ ';', ',', '.' ];
+private static readonly char[] s_trimChars = [ ';', ',', '.' ];

...

return input.Trim(s_trimChars);

영향을 받는 API

  • System.String.Trim(System.ReadOnlySpan{System.Char})
  • System.String.TrimEnd(System.ReadOnlySpan{System.Char})
  • System.String.TrimStart(System.ReadOnlySpan{System.Char})