System.Text.Rune 구조체
이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.
인스턴스는 Rune 서로게이트 범위를 제외한 모든 코드 지점(U+D800.)을 의미하는 유니코드 스칼라 값을 나타냅니다. U+DFFF). 형식의 생성자 및 변환 연산자는 입력의 유효성을 검사하므로 소비자는 기본 인스턴스가 잘 형성되어 있다고 가정하여 API를 Rune 호출할 수 있습니다.
유니코드 스칼라 값, 코드 포인트, 서로게이트 범위 및 잘 구성된 용어에 익숙하지 않은 경우 .NET의 문자 인코딩 소개를 참조하세요.
Rune 형식을 사용하는 경우
코드가 다음과 같은 경우 형식을 Rune
사용하는 것이 좋습니다.
- 유니코드 스칼라 값이 필요한 API 호출
- 서로게이트 쌍을 명시적으로 처리합니다.
유니코드 스칼라 값이 필요한 API
코드가 a 또는 a ReadOnlySpan<char>
string
의 인스턴스를 반복 char
하는 경우 일부 char
메서드는 서로게이트 범위에 있는 인스턴스에서 char
제대로 작동하지 않습니다. 예를 들어 다음 API는 스칼라 값 char
이 올바르게 작동해야 합니다.
- Char.GetNumericValue
- Char.GetUnicodeCategory
- Char.IsDigit
- Char.IsLetter
- Char.IsLetterOrDigit
- Char.IsLower
- Char.IsNumber
- Char.IsPunctuation
- Char.IsSymbol
- Char.IsUpper
다음 예제에서는 인스턴스가 char
서로게이트 코드 포인트인 경우 제대로 작동하지 않는 코드를 보여 줍니다.
// THE FOLLOWING METHOD SHOWS INCORRECT CODE.
// DO NOT DO THIS IN A PRODUCTION APPLICATION.
int CountLettersBadExample(string s)
{
int letterCount = 0;
foreach (char ch in s)
{
if (char.IsLetter(ch))
{ letterCount++; }
}
return letterCount;
}
// THE FOLLOWING METHOD SHOWS INCORRECT CODE.
// DO NOT DO THIS IN A PRODUCTION APPLICATION.
let countLettersBadExample (s: string) =
let mutable letterCount = 0
for ch in s do
if Char.IsLetter ch then
letterCount <- letterCount + 1
letterCount
다음은 다음과 같은 코드로 작동합니다.ReadOnlySpan<char>
// THE FOLLOWING METHOD SHOWS INCORRECT CODE.
// DO NOT DO THIS IN A PRODUCTION APPLICATION.
static int CountLettersBadExample(ReadOnlySpan<char> span)
{
int letterCount = 0;
foreach (char ch in span)
{
if (char.IsLetter(ch))
{ letterCount++; }
}
return letterCount;
}
앞의 코드는 영어와 같은 일부 언어에서 올바르게 작동합니다.
CountLettersInString("Hello")
// Returns 5
그러나 Osage와 같은 기본 다국어 평면 외부의 언어에서는 제대로 작동하지 않습니다.
CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟")
// Returns 0
이 메서드가 Osage 텍스트에 대해 잘못된 결과를 반환하는 이유는 Osage 문자의 char
인스턴스가 서로게이트 코드 포인트이기 때문입니다. 단일 서로게이트 코드 지점에는 문자인지 여부를 확인하기에 충분한 정보가 없습니다.
대신 사용하도록 Rune
이 코드를 변경하는 경우 메서드는 기본 다국어 평면 외부의 char
코드 포인트에서 올바르게 작동합니다.
int CountLetters(string s)
{
int letterCount = 0;
foreach (Rune rune in s.EnumerateRunes())
{
if (Rune.IsLetter(rune))
{ letterCount++; }
}
return letterCount;
}
let countLetters (s: string) =
let mutable letterCount = 0
for rune in s.EnumerateRunes() do
if Rune.IsLetter rune then
letterCount <- letterCount + 1
letterCount
다음은 다음과 같은 코드로 작동합니다.ReadOnlySpan<char>
static int CountLetters(ReadOnlySpan<char> span)
{
int letterCount = 0;
foreach (Rune rune in span.EnumerateRunes())
{
if (Rune.IsLetter(rune))
{ letterCount++; }
}
return letterCount;
}
앞의 코드는 Osage 문자를 올바르게 계산합니다.
CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟")
// Returns 8
서로게이트 쌍을 명시적으로 처리하는 코드
코드가 Rune
서로게이트 코드 지점에서 명시적으로 작동하는 API를 호출하는 경우(예: 다음 메서드) 형식을 사용하는 것이 좋습니다.
- Char.IsSurrogate
- Char.IsSurrogatePair
- Char.IsHighSurrogate
- Char.IsLowSurrogate
- Char.ConvertFromUtf32
- Char.ConvertToUtf32
예를 들어 다음 메서드에는 서로게이트 char
쌍을 처리하는 특수 논리가 있습니다.
static void ProcessStringUseChar(string s)
{
Console.WriteLine("Using char");
for (int i = 0; i < s.Length; i++)
{
if (!char.IsSurrogate(s[i]))
{
Console.WriteLine($"Code point: {(int)(s[i])}");
}
else if (i + 1 < s.Length && char.IsSurrogatePair(s[i], s[i + 1]))
{
int codePoint = char.ConvertToUtf32(s[i], s[i + 1]);
Console.WriteLine($"Code point: {codePoint}");
i++; // so that when the loop iterates it's actually +2
}
else
{
throw new Exception("String was not well-formed UTF-16.");
}
}
}
이러한 코드는 다음 예제와 같이 사용하는 Rune
경우 더 간단합니다.
static void ProcessStringUseRune(string s)
{
Console.WriteLine("Using Rune");
for (int i = 0; i < s.Length;)
{
if (!Rune.TryGetRuneAt(s, i, out Rune rune))
{
throw new Exception("String was not well-formed UTF-16.");
}
Console.WriteLine($"Code point: {rune.Value}");
i += rune.Utf16SequenceLength; // increment the iterator by the number of chars in this Rune
}
}
Rune
를 사용하지 않는 경우
코드인 경우 형식을 Rune
사용할 필요가 없습니다.
- 정확한
char
일치 항목을 찾습니다. - 알려진 char 값에 문자열을 분할합니다.
코드를 사용하는 경우 형식을 Rune
사용하면 잘못된 결과가 반환됩니다.
- 의 표시 문자 수를 계산합니다.
string
정확한 char
일치 항목 찾기
다음 코드는 검색된 특정 문자를 반복 string
하여 첫 번째 일치 항목의 인덱스를 반환합니다. 코드가 단일 char
문자로 표현되는 문자를 찾고 있으므로 이 코드를 사용하도록 Rune
변경할 필요가 없습니다.
int GetIndexOfFirstAToZ(string s)
{
for (int i = 0; i < s.Length; i++)
{
char thisChar = s[i];
if ('A' <= thisChar && thisChar <= 'Z')
{
return i; // found a match
}
}
return -1; // didn't find 'A' - 'Z' in the input string
}
알려진 문자열에서 문자열 분할 char
다음 예제와 같이 (공간) 또는 ','
(쉼표)와 같은 ' '
구분 기호를 호출 string.Split
하고 사용하는 것이 일반적입니다.
string inputString = "🐂, 🐄, 🐆";
string[] splitOnSpace = inputString.Split(' ');
string[] splitOnComma = inputString.Split(',');
코드에서 단일 char
문자로 표현되는 문자를 찾고 있으므로 여기서 사용할 Rune
필요가 없습니다.
의 표시 문자 수 계산 string
문자열의 Rune
인스턴스 수가 문자열을 표시할 때 표시되는 사용자 인식 가능 문자 수와 일치하지 않을 수 있습니다.
Rune
인스턴스는 유니코드 스칼라 값을 나타내므로 유니코드 텍스트 구분 지침을 따르는 구성 요소는 표시 문자를 계산하기 위한 구성 요소로 사용할 Rune
수 있습니다.
이 형식은 StringInfo 표시 문자 수를 계산하는 데 사용할 수 있지만 .NET 5 이상 이외의 .NET 구현에 대한 모든 시나리오에서 올바르게 계산되지는 않습니다.
자세한 내용은 Grapheme 클러스터를 참조 하세요.
를 인스턴스화하는 방법 Rune
인스턴스를 가져오는 방법에는 여러 가지가 있습니다 Rune
. 생성자를 사용하여 다음에서 직접 만들 Rune
수 있습니다.
코드 포인트입니다.
Rune a = new Rune(0x0061); // LATIN SMALL LETTER A Rune b = new Rune(0x10421); // DESERET CAPITAL LETTER ER
단일
char
.Rune c = new Rune('a');
서로게이트
char
쌍입니다.Rune d = new Rune('\ud83d', '\udd2e'); // U+1F52E CRYSTAL BALL
입력이 유효한 유니코드 스칼라 값을 나타내지 않으면 모든 생성자가 throw ArgumentException
됩니다.
Rune.TryCreate 실패 시 예외를 throw하지 않으려는 호출자에 사용할 수 있는 메서드가 있습니다.
Rune
기존 입력 시퀀스에서 인스턴스를 읽을 수도 있습니다. 예를 들어 ReadOnlySpan<char>
UTF-16 데이터를 나타내는 경우 메서드는 Rune.DecodeFromUtf16 입력 범위의 시작 부분에 첫 번째 Rune
인스턴스를 반환합니다. 메서드도 Rune.DecodeFromUtf8 마찬가지로 작동하여 ReadOnlySpan<byte>
UTF-8 데이터를 나타내는 매개 변수를 허용합니다. 범위의 시작이 아니라 범위의 끝에서 읽는 것과 동일한 메서드가 있습니다.
의 쿼리 속성 Rune
인스턴스의 정수 코드 포인트 값을 Rune
얻으려면 속성을 사용합니다 Rune.Value .
Rune rune = new Rune('\ud83d', '\udd2e'); // U+1F52E CRYSTAL BALL
int codePoint = rune.Value; // = 128302 decimal (= 0x1F52E)
형식에서 사용할 수 있는 char
많은 정적 API도 형식에서 Rune
사용할 수 있습니다. 예를 들어, Rune.IsWhiteSpaceRune.GetUnicodeCategory 동일한 메서드와 Char.GetUnicodeCategory 같습니다Char.IsWhiteSpace. 메서드는 Rune
서로게이트 쌍을 올바르게 처리합니다.
다음 예제 코드는 입력으로 ReadOnlySpan<char>
사용하고 문자나 숫자가 아닌 모든 Rune
범위의 시작과 끝에서 트리밍합니다.
static ReadOnlySpan<char> TrimNonLettersAndNonDigits(ReadOnlySpan<char> span)
{
// First, trim from the front.
// If any Rune can't be decoded
// (return value is anything other than "Done"),
// or if the Rune is a letter or digit,
// stop trimming from the front and
// instead work from the end.
while (Rune.DecodeFromUtf16(span, out Rune rune, out int charsConsumed) == OperationStatus.Done)
{
if (Rune.IsLetterOrDigit(rune))
{ break; }
span = span[charsConsumed..];
}
// Next, trim from the end.
// If any Rune can't be decoded,
// or if the Rune is a letter or digit,
// break from the loop, and we're finished.
while (Rune.DecodeLastFromUtf16(span, out Rune rune, out int charsConsumed) == OperationStatus.Done)
{
if (Rune.IsLetterOrDigit(rune))
{ break; }
span = span[..^charsConsumed];
}
return span;
}
API 간에는 몇 가지 API 차이점이 있습니다 char
Rune
. 예시:
- 정의별 인스턴스는 서로게이트 코드 포인트가 될 수 없으므로 동일한 Char.IsSurrogate(Char)
Rune
값은 없습니다Rune
. - 항상 Rune.GetUnicodeCategory .와 동일한 결과를 Char.GetUnicodeCategory반환하지는 않습니다. 와 동일한 값을 CharUnicodeInfo.GetUnicodeCategory반환합니다. 자세한 내용은 에 대한 비고를 참조하세요Char.GetUnicodeCategory.
Rune
UTF-8 또는 UTF-16으로 변환
유니 Rune
코드 스칼라 값이므로 UTF-8, UTF-16 또는 UTF-32 인코딩으로 변환할 수 있습니다. 이 Rune
형식은 UTF-8 및 UTF-16으로의 변환을 기본적으로 지원합니다.
Rune.EncodeToUtf16 인스턴스를 인스턴스로 Rune
char
변환합니다. 인스턴스를 UTF-16으로 변환하여 Rune
발생하는 인스턴스 수를 char
쿼리하려면 이 속성을 사용합니다Rune.Utf16SequenceLength. UTF-8 변환에서도 비슷한 메서드가 있습니다.
다음 예제에서는 인스턴스를 Rune
배열로 char
변환합니다. 이 코드는 변수에 인스턴스가 Rune
있다고 가정합니다 rune
.
char[] chars = new char[rune.Utf16SequenceLength];
int numCharsWritten = rune.EncodeToUtf16(chars);
A string
는 UTF-16 문자 시퀀스이므로 다음 예제에서는 인스턴스를 UTF-16으로 변환합니다 Rune
.
string theString = rune.ToString();
다음 예제에서는 인스턴스를 Rune
바이트 배열로 UTF-8
변환합니다.
byte[] bytes = new byte[rune.Utf8SequenceLength];
int numBytesWritten = rune.EncodeToUtf8(bytes);
및 Rune.EncodeToUtf8 메서드는 Rune.EncodeToUtf16 작성된 실제 요소 수를 반환합니다. 대상 버퍼가 너무 짧아 결과를 포함할 수 없는 경우 예외를 throw합니다. 예외를 TryEncodeToUtf8TryEncodeToUtf16 방지하려는 호출자뿐만 아니라 throw되지 않는 메서드도 있습니다.
.NET 및 기타 언어로 실행
"rune"이라는 용어는 유니코드 표준에 정의되어 있지 않습니다. 이 용어는 UTF-8 생성으로 거슬러 올라갑니다. 롭 파이크와 켄 톰슨은 결국 코드 포인트로 알려질 것을 설명하는 용어를 찾고 있었다. 그들은 "rune"이라는 용어에 정착했고, Rob Pike는 나중에 Go 프로그래밍 언어에 대한 영향력을 통해 이 용어를 대중화하는 데 도움을 주었습니다.
그러나 .NET Rune
형식은 Go rune
형식과 동일하지 않습니다. Go rune
에서 형식은 . 에 대한 int32
별칭입니다. Go rune은 유니코드 코드 포인트를 나타내기 위한 것이지만 서로게이트 코드 포인트 및 유효한 유니코드 코드 포인트가 아닌 값을 포함하여 32비트 값일 수 있습니다.
다른 프로그래밍 언어의 유사한 형식은 Rust의 기본 형식 또는 Swift의 Unicode.Scalar
형식을 참조하세요. 둘 다 유니코드 스칼라 값을 char
나타냅니다. 다음과 유사한 기능을 제공합니다. NET의 Rune
형식이며, 합법적인 유니코드 스칼라 값이 아닌 값의 인스턴스화를 허용하지 않습니다.
.NET