다음을 통해 공유


상수 문자열의 패턴 일치 Span<char>

메모

이 문서는 기능 사양입니다. 사양은 기능의 디자인 문서 역할을 합니다. 여기에는 기능 디자인 및 개발 중에 필요한 정보와 함께 제안된 사양 변경 내용이 포함됩니다. 이러한 문서는 제안된 사양 변경이 완료되고 현재 ECMA 사양에 통합될 때까지 게시됩니다.

기능 사양과 완료된 구현 간에 약간의 불일치가 있을 수 있습니다. 해당 차이점들은 언어 디자인 회의(LDM) 관련노트에 기록되어 있습니다.

사양문서에서 C# 언어 표준에 '기능 사양서'를 채택하는 과정에 대해 더 자세히 알아볼 수 있습니다.

챔피언 이슈: https://github.com/dotnet/csharplang/issues/8640

요약

상수 문자열에서 Span<char>ReadOnlySpan<char>에 대한 패턴 일치를 허용합니다.

동기

성능의 경우 많은 시나리오에서 문자열보다 Span<char>ReadOnlySpan<char> 사용하는 것이 좋습니다. 프레임워크는 ReadOnlySpan<char>대신 string 사용할 수 있도록 많은 새 API를 추가했습니다.

문자열에 대한 일반적인 작업은 스위치를 사용하여 특정 값인지 테스트하는 것이며 컴파일러는 이러한 스위치를 최적화합니다. 그러나 현재는 스위치 및 최적화를 수동으로 구현하는 것 외에는 ReadOnlySpan<char>에서 동일한 작업을 효율적으로 수행할 방법이 없습니다.

ReadOnlySpan<char>의 채택을 장려하기 위해, 우리는 ReadOnlySpan<char>와 같은 상수에 대해 string패턴 매칭을 허용하여 스위치에서도 사용할 수 있습니다.

static bool Is123(ReadOnlySpan<char> s)
{
    return s is "123";
}

static bool IsABC(Span<char> s)
{
    return s switch { "ABC" => true, _ => false };
}

상세 디자인

다음과 같이 상수 패턴에 대한 사양을 변경합니다(굵게 표시된 부분이 제안된 추가입니다).

패턴 입력 값 e 및 변환된 값이 P인 상수 패턴 v이 주어진 경우

  • e가 정수형 또는 열거형, 또는 그 nullable 형태를 가질 때, v가 정수형인 경우, 패턴 P와 일치시킵니다. 그렇지 않으면
  • eSystem.Span<char> 또는 System.ReadOnlySpan<char>형식이고 c 상수 문자열이고 c 상수 값이 null없는 경우 System.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))true반환하는 경우 패턴이 일치하는 것으로 간주됩니다.
  • 패턴 P.

잘 알려진 멤버

System.Span<T>System.ReadOnlySpan<T>은 이름으로 일치해야 하며, ref struct이어야 하고 corlib 외부에서 정의할 수 있습니다.

System.MemoryExtensions는 이름에 의해 매칭되며 corlib 외부에서 정의할 수 있습니다.

System.MemoryExtensions.SequenceEqual 오버로드의 서명은 다음과 일치해야 합니다.

  • public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
  • public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)

System.MemoryExtensions.AsSpan 서명은 다음과 일치해야 합니다.

  • public static System.ReadOnlySpan<char> AsSpan(string)

선택적 매개 변수가 있는 메서드는 고려 사항에서 제외됩니다.

단점

없음

대안

없음

해결되지 않은 질문

  1. 매칭은 MemoryExtensions.SequenceEqual() 등과 독립하여 정의되어야 하나요?

    ... 패턴은 e.Length == c.Length의 모든 문자에 대해 e[i] == c[i]e이 적용되는 경우 일치하는 것으로 간주됩니다.

    권장 사항: 성능을 기준으로 MemoryExtensions.SequenceEqual() 측면에서 정의합니다. MemoryExtensions 누락된 경우 컴파일 오류를 보고합니다.

  2. (string)null에 대한 매칭이 허용되어야 하나요?

    그렇다면 (string)null이후 ""MemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")을 포함해야 하나요?

    static bool IsEmpty(ReadOnlySpan<char> span)
    {
        return span switch
        {
            (string)null => true, // ok?
            "" => true,           // error: unreachable?
            _ => false,
        };
    }
    

    권장 사항: 일정한 패턴 (string)null을 오류로 간주해야 합니다.

  3. 상수 패턴 일치에 Span<char> 또는 ReadOnlySpan<char>식 값의 런타임 형식 테스트가 포함되어야 하나요?

    static bool Is123<T>(Span<T> s)
    {
        return s is "123"; // test for Span<char>?
    }
    
    static bool IsABC<T>(Span<T> s)
    {
        return s is Span<char> and "ABC"; // ok?
    }
    
    static bool IsEmptyString<T>(T t) where T : ref struct
    {
        return t is ""; // test for ReadOnlySpan<char>, Span<char>, string?
    }
    

    권장 사항: 상수 패턴에 대한 암시적 런타임 형식 테스트가 없습니다. (IsABC<T>() 예제는 형식 테스트가 명시적이므로 허용됩니다.)

    이 권장 사항은 구현되지 않았습니다. 위의 모든 샘플은 컴파일러 오류를 생성합니다.

  4. 포함 관계는 상수 문자열 패턴, 목록 패턴 및 Length 속성 패턴을 고려해야 하나요?

    static int ToNum(ReadOnlySpan<char> s)
    {
        return s switch
        {
            { Length: 0 } => 0,
            "" => 1,        // error: unreachable?
            ['A',..] => 2,
            "ABC" => 3,     // error: unreachable?
            _ => 4,
        };
    }
    

    권장 사항: 식 값이 string때 사용되는 것과 동일한 하위 가정 동작입니다. Length을 일치하는 것으로 처리하는 것 외에는 상수 문자열, 목록 패턴, [..]간의 포함 관계가 없음을 의미하나요?

디자인 회의

https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md#readonlyspanchar-patterns