Rune Структура

Определение

Представляет скалярное значение Юникода ([U+0000.. U+D7FF] включительно или [U+E000..U+10FFFF] включительно).

public value class Rune : IComparable, IComparable<System::Text::Rune>, IEquatable<System::Text::Rune>
public value class Rune : IComparable, IComparable<System::Text::Rune>, IEquatable<System::Text::Rune>, ISpanFormattable
public value class Rune : IComparable<System::Text::Rune>, IEquatable<System::Text::Rune>
public struct Rune : IComparable, IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>
public struct Rune : IComparable, IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>, ISpanFormattable
public struct Rune : IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>
type Rune = struct
type Rune = struct
    interface ISpanFormattable
    interface IFormattable
Public Structure Rune
Implements IComparable, IComparable(Of Rune), IEquatable(Of Rune)
Public Structure Rune
Implements IComparable, IComparable(Of Rune), IEquatable(Of Rune), ISpanFormattable
Public Structure Rune
Implements IComparable(Of Rune), IEquatable(Of Rune)
Наследование
Реализации

Комментарии

RuneЭкземпляр представляет скалярное значение Юникода, означающее, что любая кодовая точка, исключая суррогатный диапазон (U + D800. U + DFFF). Конструкторы типа и операторы преобразования проверяют входные данные, поэтому потребители могут вызывать API, предполагая, что базовый Rune экземпляр правильно сформирован.

Если вы не знакомы с условиями скалярного значения в Юникоде, кодовой точки, суррогатного диапазона и правильного формата, см. статью Введение в кодировку символов в .NET.

В следующих разделах описывается:

Когда следует использовать тип Руне

Используйте тип, Rune Если код:

  • Вызывает API, требующие скалярных значений в Юникоде
  • Явно обрабатывает суррогатные пары

API, для которых требуются скалярные значения Юникода

Если код проходит через char экземпляры в string или ReadOnlySpan<char> , некоторые char методы не будут правильно работать на экземплярах, находящийся char в диапазоне суррогатов. Например, для правильной работы следующих API требуется скалярное значение char :

В следующем примере показан код, который будет работать неправильно, если любой из 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;
}

Вот эквивалентный код, который работает с 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

Но он будет работать неправильно для языков, не входящих в стандартную многоязыковую плоскость, например Осаже:

CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟")
// Returns 0

Причина, по которой этот метод возвращает неверные результаты для Осаже текста, заключается в том, что char экземпляры для осаже букв являются суррогатными кодовыми точками. Ни одна суррогатная кодовая точка не содержит достаточно информации, чтобы определить, является ли она буквой.

Если изменить этот код для использования Rune вместо char , метод будет правильно работать с точками кода за пределами базовой многоязычной плоскости:

int CountLetters(string s)
{
    int letterCount = 0;

    foreach (Rune rune in s.EnumerateRunes())
    {
        if (Rune.IsLetter(rune))
        { letterCount++; }
    }

    return 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;
}

Приведенный выше код правильно подсчитывает Осаже буквы.

CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟")
// Returns 8

Код, который явно обрабатывает суррогатные пары

Используйте тип, Rune Если ваш код вызывает API-интерфейсы, которые явно работают с суррогатными кодовыми точками, например следующие методы:

Например, следующий метод имеет специальную логику для работы с суррогатными 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 поиску конкретных символов, возвращая индекс первого совпадения. Нет необходимости изменять этот код для использования Rune , так как код ищет символы, представленные одним char .

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(',');

Здесь нет необходимости использовать Rune , поскольку код ищет символы, представленные одним char .

Подсчитайте количество отображаемых символов в элементе string

Количество Rune экземпляров в строке может не совпадать с числом воспринимаемого символов, отображаемым при отображении строки.

Поскольку Rune экземпляры представляют собой скалярные значения в Юникоде, компоненты, которые следуют правилам сегментации текста Юникода , могут использовать Rune в качестве стандартного блока для подсчета отображаемых символов.

StringInfoТип можно использовать для подсчета отображаемых символов, но он неверно учитывается во всех сценариях для реализаций .NET, отличных от .NET 5 +.

Дополнительные сведения см. в разделе кластеры графеме.

Как создать экземпляр 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
    

Все конструкторы создают исключение, ArgumentException Если входные данные не представляют Допустимое скалярное значение Юникода.

Существуют Rune.TryCreate методы, доступные для вызывающих объектов, которые не хотят вызывать исключения при сбое.

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)

Многие из статических интерфейсов API, доступных для char типа, также доступны в Rune типе. Например, Rune.IsWhiteSpace методы и Rune.GetUnicodeCategory эквивалентны Char.IsWhiteSpace Char.GetUnicodeCategory методам и. 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 между char и Rune . Пример:

Преобразование в Rune UTF-8 или UTF-16

Поскольку объект Rune является скалярным значением Юникода, его можно преобразовать в кодировку UTF-8, UTF-16 или UTF-32. RuneТип имеет встроенную поддержку преобразования в UTF-8 и UTF-16.

Rune.EncodeToUtf16Преобразует Rune экземпляр в char экземпляры. Чтобы запросить количество char экземпляров, которые могут быть результатом преобразования Rune экземпляра в UTF-16, используйте Rune.Utf16SequenceLength свойство. Аналогичные методы существуют для преобразования UTF-8.

В следующем примере экземпляр преобразуется Rune в char массив. В коде предполагается, что у вас есть Rune экземпляр в rune переменной:

char[] chars = new char[rune.Utf16SequenceLength];
int numCharsWritten = rune.EncodeToUtf16(chars);

Поскольку string представляет собой последовательность символов UTF-16, следующий пример также преобразует Rune экземпляр в UTF-16:

string theString = rune.ToString();

В следующем примере экземпляр преобразуется Rune в UTF-8 массив байтов:

byte[] bytes = new byte[rune.Utf8SequenceLength];
int numBytesWritten = rune.EncodeToUtf8(bytes);

Rune.EncodeToUtf16Методы и Rune.EncodeToUtf8 возвращают фактическое число записанных элементов. Они вызовут исключение, если буфер назначения слишком короткий и не может содержать результат. Существуют методы и, Кроме того, TryEncodeToUtf8 EncodeToUtf16 для вызывающих объектов, желающих избежать исключений.

Руне в .NET и других языках

Термин "Руне" не определен в стандарте Юникода. Термин даты возвращается к созданию UTF-8. Вадиму Пайк и Кен Thompson искали термин для описания того, что в конечном итоге стало известным как кодовая точка. Они были сопоставлены с термином «Руне», а Вадим Пайк в будущем влияет на язык программирования Go, помогая популяризировала этот термин.

Однако Rune тип .NET не эквивалентен rune типу go. В Go rune тип является псевдонимом int32 для . Руне Go предназначен для представления кодовой точки Юникода, но может быть любым 32-битным значением, включая суррогатные кодовые точки и значения, которые не являются допустимыми кодовыми точками Юникода.

Аналогичные типы в других языках программирования см. в разделе char тип-примитив Руст или Unicode.Scalar тип SWIFT, оба из которых представляют скалярные значения Юникода. Они предоставляют функциональные возможности, аналогичные. Тип NET Rune и запрещает создание экземпляров значений, которые не являются допустимыми скалярными значениями в Юникоде.

Конструкторы

Rune(Char)

Создает объект Rune из предоставленного блока кода UTF-16.

Rune(Char, Char)

Создает объект Rune из предоставленной суррогатной пары UTF-16.

Rune(Int32)

Создает Rune из указанного 32-разрядного целого числа, представляющего скалярное значение Юникода.

Rune(UInt32)

Создает Rune из указанного 32-разрядного целого числа без знака, представляющего скалярное значение Юникода.

Свойства

IsAscii

Возвращает значение, указывающее, находится ли скалярное значение, связанное с этим Rune, в диапазоне кодирования ASCII.

IsBmp

Возвращает значение, указывающее, находится ли скалярное значение, связанное с этим Rune, в диапазоне кодирования BMP.

Plane

Возвращает плоскость Юникода (от 0 до 16 включительно), которая содержит этот скаляр.

ReplacementChar

Возвращает экземпляр Rune, представляющий символ замены Юникода U+FFFD.

Utf16SequenceLength

Возвращает длину в блоках кода (Char) для последовательности UTF-16, которая должна представлять это скалярное значение.

Utf8SequenceLength

Возвращает длину в блоках для последовательности UTF-8, которая должна представлять это скалярное значение.

Value

Возвращает скалярное значение Юникода в виде целого числа.

Методы

CompareTo(Rune)

Сравнивает текущий экземпляр с указанным экземпляром Rune.

DecodeFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Декодирует в Rune начале предоставленного исходного буфера UTF-16.

DecodeFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Декодирует в Rune начале предоставленного исходного буфера UTF-8.

DecodeLastFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Декодирует Rune в конце предоставленного исходного буфера UTF-16.

DecodeLastFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Декодирует Rune в конце предоставленного исходного буфера UTF-8.

EncodeToUtf16(Span<Char>)

Кодирует это Rune в буфер назначения UTF-16.

EncodeToUtf8(Span<Byte>)

Кодирует это Rune в буфер назначения UTF-8.

Equals(Object)

Возвращает значение, указывающее, равен ли данный экземпляр указанному объекту.

Equals(Rune)

Возвращает значение, указывающее, равен ли данный экземпляр указанной руне.

GetHashCode()

Возвращает хэш-код данного экземпляра.

GetNumericValue(Rune)

Получает числовое значение, связанное с указанной руной.

GetRuneAt(String, Int32)

Возвращает объект Rune, начинающийся с указанной позиции в строке.

GetUnicodeCategory(Rune)

Получает категорию Юникода, связанную с указанной руной.

IsControl(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории управляющих символов.

IsDigit(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории десятичных чисел.

IsLetter(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории букв.

IsLetterOrDigit(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории букв или десятичных чисел.

IsLower(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории букв нижнего регистра.

IsNumber(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории цифр.

IsPunctuation(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории знаков препинания.

IsSeparator(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории знаков разделения.

IsSymbol(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории знаков символов.

IsUpper(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории букв верхнего регистра.

IsValid(Int32)

Возвращает значение, указывающее, представляет ли 32-разрядное целое число со знаком допустимое скалярное значение Юникода, то есть находится ли оно в диапазоне [U+0000..U+D7FF] включительно или [U+ E000..U+10FFFF] включительно.

IsValid(UInt32)

Возвращает значение, указывающее, представляет ли 32-разрядное целое число без знака допустимое скалярное значение Юникода, то есть находится ли оно в диапазоне [U+0000..U+D7FF] включительно или [U+ E000..U+10FFFF] включительно.

IsWhiteSpace(Rune)

Возвращает значение, которое показывает, относится ли указанная руна к категории пробелов.

ToLower(Rune, CultureInfo)

Возвращает копию заданного Rune, преобразованного в нижний регистр, используя правила определения регистра заданного языка и региональных параметров.

ToLowerInvariant(Rune)

Возвращает копию указанного Rune, преобразованного в нижний регистр, используя правила учета регистра инвариантного языка и региональных параметров.

ToString()

Возвращает строковое представление этого экземпляра Rune.

ToUpper(Rune, CultureInfo)

Возвращает копию заданного Rune, преобразованного в верхний регистр, используя правила определения регистра заданного языка и региональных параметров.

ToUpperInvariant(Rune)

Возвращает копию указанного Rune, преобразованного в верхний регистр, используя правила учета регистра инвариантного языка и региональных параметров.

TryCreate(Char, Char, Rune)

Пытается создать Rune из указанной суррогатной пары в UTF-16 и возвращает значение, указывающее, успешно ли выполнена операция.

TryCreate(Char, Rune)

Пытается создать Rune из указанного символа и возвращает значение, указывающее, успешно ли выполнена операция.

TryCreate(Int32, Rune)

Пытается создать Rune из указанного целого числа со знаком, представляющего скалярное значение Юникода.

TryCreate(UInt32, Rune)

Пытается создать Rune из указанного целого 32-разрядного числа без знака, представляющего скалярное значение Юникода.

TryEncodeToUtf16(Span<Char>, Int32)

Кодирует это Rune в буфер назначения в кодировке UTF-16.

TryEncodeToUtf8(Span<Byte>, Int32)

Кодирует это Rune в буфер назначения в кодировке UTF-8.

TryGetRuneAt(String, Int32, Rune)

Пытается получить объект Rune, начинающийся с указанной позиции в строке, и возвращает значение, указывающее, завершилась ли операция успехом.

Операторы

Equality(Rune, Rune)

Возвращает значение, указывающее, равны ли два экземпляра Rune.

Explicit(Char to Rune)

Определяет явное преобразование 16-разрядного символа Юникода в Rune.

Explicit(Int32 to Rune)

Определяет явное преобразование 32-разрядного целого числа со знаком в значение Rune.

Explicit(UInt32 to Rune)

Определяет явное преобразование 32-разрядного целого числа без знака в значение Rune.

GreaterThan(Rune, Rune)

Возвращает значение, позволяющее определить, действительно ли заданное значение типа Rune больше другого заданного значения типа Rune.

GreaterThanOrEqual(Rune, Rune)

Возвращает значение, позволяющее определить, действительно ли заданное значение типа Rune больше или равно другому заданному значению типа Rune.

Inequality(Rune, Rune)

Возвращает значение, указывающее, различаются ли значения двух экземпляров Rune.

LessThan(Rune, Rune)

Возвращает значение, позволяющее определить, действительно ли заданное значение типа Rune меньше другого заданного значения типа Rune.

LessThanOrEqual(Rune, Rune)

Возвращает значение, позволяющее определить, действительно ли заданное значение типа Rune меньше или равно другому заданному значению типа Rune.

Явные реализации интерфейса

IComparable.CompareTo(Object)

Сравнивает текущий экземпляр с указанным объектом.

IFormattable.ToString(String, IFormatProvider)

Форматирует значение текущего экземпляра, используя указанный формат.

ISpanFormattable.TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)

Пытается отформатировать значение текущего экземпляра в указанный диапазон символов.

Применяется к