Rune Estrutura

Definição

Representa um valor escalar Unicode ([ U+0000.U+D7FF ], inclusive; ou [ U+E000.. U+10FFFF ], inclusive).

public value class Rune : IComparable, IComparable<System::Text::Rune>, IEquatable<System::Text::Rune>, ISpanFormattable, IUtf8SpanFormattable, IUtf8SpanParsable<System::Text::Rune>
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, IComparable<System::Text::Rune>, IEquatable<System::Text::Rune>, ISpanFormattable, IUtf8SpanFormattable
public value class Rune : IComparable<System::Text::Rune>, IEquatable<System::Text::Rune>
public readonly struct Rune : IComparable, IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>, ISpanFormattable, IUtf8SpanFormattable, IUtf8SpanParsable<System.Text.Rune>
public readonly struct Rune : IComparable, IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>
public readonly struct Rune : IComparable, IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>, ISpanFormattable
public readonly struct Rune : IComparable, IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>, ISpanFormattable, IUtf8SpanFormattable
public readonly struct Rune : IComparable<System.Text.Rune>, IEquatable<System.Text.Rune>
type Rune = struct
    interface IFormattable
    interface ISpanFormattable
    interface IUtf8SpanFormattable
    interface IUtf8SpanParsable<Rune>
type Rune = struct
type Rune = struct
    interface ISpanFormattable
    interface IFormattable
type Rune = struct
    interface IFormattable
    interface ISpanFormattable
type Rune = struct
    interface IFormattable
    interface ISpanFormattable
    interface IUtf8SpanFormattable
Public Structure Rune
Implements IComparable, IComparable(Of Rune), IEquatable(Of Rune), ISpanFormattable, IUtf8SpanFormattable, IUtf8SpanParsable(Of Rune)
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, IComparable(Of Rune), IEquatable(Of Rune), ISpanFormattable, IUtf8SpanFormattable
Public Structure Rune
Implements IComparable(Of Rune), IEquatable(Of Rune)
Herança
Implementações

Comentários

Uma Rune instância representa um valor escalar Unicode, o que significa qualquer ponto de código, excluindo o intervalo alternativo (U+D800.. U+DFFF). Os construtores e operadores de conversão do tipo validam a entrada, para que os consumidores possam chamar as APIs supondo que a instância subjacente Rune esteja bem formada.

Se você não estiver familiarizado com os termos valor escalar Unicode, ponto de código, intervalo substituto e bem-formado, consulte a Introdução à codificação de caracteres no .NET.

Quando usar o tipo rune

Considere usar o tipo Rune se o seu código:

  • Chama APIs que exigem valores escalares Unicode
  • Lida explicitamente com pares substitutos

APIs que exigem valores escalares Unicode

Se o seu código iterar através das char instâncias em um string ou um ReadOnlySpan<char>, alguns dos métodos char não funcionarão corretamente em char instâncias que estão na faixa de substituição. Por exemplo, as seguintes APIs exigem um valor char escalar para funcionar corretamente:

O exemplo a seguir mostra o código que não funcionará corretamente se qualquer uma das char instâncias for um ponto de código alternativo:

// 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

Aqui está o código equivalente que funciona com um 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;
}

O código anterior funciona corretamente com alguns idiomas, como inglês:

CountLettersInString("Hello")
// Returns 5

Mas não funcionará corretamente para idiomas fora do Plano Multilíngue Básico, como Osage:

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

O motivo pelo qual esse método retorna resultados incorretos para o texto de Osage é que as char instâncias das letras osage são pontos de código alternativos. Nenhum único ponto de código alternativo tem informações suficientes para determinar se é uma letra.

Se você alterar esse código para usar Rune em vez de char, o método funcionará corretamente com pontos de código fora do Plano Multilíngue Básico:

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

Aqui está o código equivalente que funciona com um ReadOnlySpan<char>:

static int CountLetters(ReadOnlySpan<char> span)
{
    int letterCount = 0;

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

    return letterCount;
}

O código anterior conta as Letras Osage corretamente.

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

Código que trata explicitamente pares substitutos

Considere usar o tipo Rune se o seu código chamar APIs que operam explicitamente em pontos de código substitutos, como os seguintes métodos:

Por exemplo, o método a seguir tem uma lógica especial para lidar com pares alternativos 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.");
        }
    }
}

Esse código será mais simples se ele usar Rune, como no exemplo a seguir:

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

Quando não usar Rune

Você não precisará usar o tipo Rune se o seu código:

  • Procura correspondências exatas char.
  • Divide uma cadeia de caracteres em um valor char conhecido

O uso do Rune tipo poderá retornar resultados incorretos se o código:

  • Conta o número de caracteres visíveis em um string

Procure correspondências exatas char.

O código a seguir itera por meio de uma string busca por caracteres específicos, retornando o índice da primeira correspondência. Não há necessidade de alterar este código para usar Rune, já que o código está procurando por caracteres que são representados por um único 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
}

Dividir uma cadeia de caracteres em torno de um separador conhecido char

É comum chamar string.Split e usar delimitadores como ' ' (espaço) ou ',' (vírgula), como no exemplo a seguir:

string inputString = "🐂, 🐄, 🐆";
string[] splitOnSpace = inputString.Split(' ');
string[] splitOnComma = inputString.Split(',');

Não é necessário usar Rune aqui, pois o código está procurando caracteres que são representados por um único char.

Contar o número de caracteres de exibição em um string

O número de Rune instâncias em uma string pode não corresponder ao número de caracteres visíveis ao usuário exibidos ao mostrar a string.

Como Rune as instâncias representam valores escalares Unicode, componentes que seguem as diretrizes de segmentação de texto Unicode podem usar Rune como um bloco de construção para a contagem de caracteres de exibição.

O StringInfo tipo pode ser usado para contar caracteres visíveis, mas não conta corretamente em todos os cenários para implementações do .NET que não sejam .NET 5+.

Para obter mais informações, consulte clusters do Grapheme.

Como instanciar um Rune

Há várias maneiras de obter uma instância Rune. Você pode usar um construtor para criar um Rune diretamente de:

  • Um ponto de código.

    Rune a = new Rune(0x0061); // LATIN SMALL LETTER A
    Rune b = new Rune(0x10421); // DESERET CAPITAL LETTER ER
    
  • Um único char.

    Rune c = new Rune('a');
    
  • Um par char alternativa.

    Rune d = new Rune('\ud83d', '\udd2e'); // U+1F52E CRYSTAL BALL
    

Todos os construtores lançarão um ArgumentException se a entrada não representar um valor escalar Unicode válido.

Rune.TryCreate métodos disponíveis para chamadores que não querem que exceções sejam geradas em caso de falha.

Rune as instâncias também podem ser lidas de sequências de entrada existentes. Por exemplo, dado um ReadOnlySpan<char> que representa dados UTF-16, o Rune.DecodeFromUtf16 método retorna a primeira Rune instância no início do intervalo de entrada. O Rune.DecodeFromUtf8 método opera da mesma forma, aceitando um ReadOnlySpan<byte> parâmetro que representa dados UTF-8. Existem métodos equivalentes para ler a partir do final da extensão em vez do início da extensão.

Consultar propriedades de um Rune

Para obter o valor inteiro de ponto de código de uma instância Rune, use a propriedade Rune.Value.

Rune rune = new Rune('\ud83d', '\udd2e'); // U+1F52E CRYSTAL BALL
int codePoint = rune.Value; // = 128302 decimal (= 0x1F52E)

Muitas das APIs estáticas disponíveis no char tipo também estão disponíveis no Rune tipo. Por exemplo, Rune.IsWhiteSpace e Rune.GetUnicodeCategory são equivalentes aos métodos Char.IsWhiteSpace e Char.GetUnicodeCategory. Os Rune métodos lidam corretamente com pares substitutos.

O código de exemplo a seguir recebe uma ReadOnlySpan<char> como entrada e remove tanto do início quanto do final da sequência cada Rune que não seja uma letra ou um dígito.

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

Há algumas diferenças de API entre char e Rune. Por exemplo:

Converter um Rune em UTF-8 ou UTF-16

Como é um Rune valor escalar Unicode, ele pode ser convertido em codificação UTF-8, UTF-16 ou UTF-32. O Rune tipo tem suporte interno para conversão em UTF-8 e UTF-16.

O Rune.EncodeToUtf16 converte uma instância de Rune em instâncias de char. Para consultar o número de instâncias char resultantes da conversão de uma instância Rune para UTF-16, use a propriedade Rune.Utf16SequenceLength. Existem métodos semelhantes para conversão UTF-8.

O exemplo a seguir converte uma Rune instância em uma char matriz. O código pressupõe que você tenha uma Rune instância na rune variável:

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

Como uma instância de string é uma sequência de caracteres UTF-16, o exemplo a seguir também converte uma instância de Rune para UTF-16.

string theString = rune.ToString();

O exemplo a seguir converte uma Rune instância em uma UTF-8 matriz de bytes:

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

Os Rune.EncodeToUtf16 métodos e os Rune.EncodeToUtf8 métodos retornam o número real de elementos gravados. Eles geram uma exceção se o buffer de destino for muito curto para conter o resultado. Existem métodos não lançantes TryEncodeToUtf8 e TryEncodeToUtf16 também para usuários que desejam evitar exceções.

Rune no .NET vs. outras linguagens

O termo "rune" não está definido no Padrão Unicode. O termo remonta à criação do UTF-8. Rob Pike e Ken Thompson estavam procurando um termo para descrever o que eventualmente se tornaria conhecido como um ponto de código. Eles se estabeleceram no termo "rune", e a influência posterior de Rob Pike sobre a linguagem de programação Go ajudou a popularizar o termo.

No entanto, o tipo .NET Rune não é o equivalente do tipo Go rune . Em Ir, o tipo rune é um alias de int32. Um rune Go destina-se a representar um ponto de código Unicode, mas pode ser qualquer valor de 32 bits, incluindo pontos de código alternativos e valores que não são pontos de código Unicode legais.

Para tipos semelhantes em outras linguagens de programação, consulte o tipo primitivo char do Rust ou o tipo de Unicode.Scalar Swift, que representam valores escalares Unicode. Eles fornecem funcionalidade semelhante ao tipo Rune do .NET, e não permitem a instanciação de valores que não sejam valores escalares Unicode válidos.

Construtores

Nome Description
Rune(Char, Char)

Cria um Rune do par alternativo UTF-16 fornecido.

Rune(Char)

Cria uma Rune unidade de código UTF-16 fornecida.

Rune(Int32)

Cria um Rune inteiro de 32 bits especificado que representa um valor escalar Unicode.

Rune(UInt32)

Cria um Rune inteiro sem sinal de 32 bits especificado que representa um valor escalar Unicode.

Propriedades

Nome Description
IsAscii

Obtém um valor que indica se o valor escalar associado a isso Rune está dentro do intervalo de codificação ASCII.

IsBmp

Obtém um valor que indica se o valor escalar associado a isso Rune está dentro do intervalo de codificação BMP.

Plane

Obtém o plano Unicode (0 a 16, inclusive) que contém esse escalar.

ReplacementChar

Obtém uma Rune instância que representa o caractere de substituição Unicode U+FFFD.

Utf16SequenceLength

Obtém o comprimento em unidades de código (Char) da sequência UTF-16 necessária para representar esse valor escalar.

Utf8SequenceLength

Obtém o comprimento em unidades de código da sequência UTF-8 necessária para representar esse valor escalar.

Value

Obtém o valor escalar Unicode como um inteiro.

Métodos

Nome Description
CompareTo(Rune)

Compara a instância atual com a instância especificada Rune .

DecodeFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Decodifica o buffer de origem Rune UTF-16 no início do utf-16 fornecido.

DecodeFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Decodifica o buffer de origem Rune UTF-8 no início do utf-8 fornecido.

DecodeLastFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Decodifica o buffer de origem Rune UTF-16 no final do utf-16 fornecido.

DecodeLastFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Decodifica o buffer de origem Rune UTF-8 no final do utf-8 fornecido.

EncodeToUtf16(Span<Char>)

Codifica isso Rune em um buffer de destino UTF-16.

EncodeToUtf8(Span<Byte>)

Codifica isso Rune em um buffer de destino UTF-8.

Equals(Object)

Retorna um valor que indica se a instância atual e um objeto especificado são iguais.

Equals(Rune, StringComparison)

Representa um valor escalar Unicode ([ U+0000.U+D7FF ], inclusive; ou [ U+E000.. U+10FFFF ], inclusive).

Equals(Rune)

Retorna um valor que indica se a instância atual e um rune especificado são iguais.

GetHashCode()

Retorna o código hash dessa instância.

GetNumericValue(Rune)

Obtém o valor numérico associado ao rune especificado.

GetRuneAt(String, Int32)

Obtém o Rune que começa em uma posição especificada em uma cadeia de caracteres.

GetUnicodeCategory(Rune)

Obtém a categoria Unicode associada ao rune especificado.

IsControl(Rune)

Retorna um valor que indica se o rune especificado é categorizado como um caractere de controle.

IsDigit(Rune)

Retorna um valor que indica se o rune especificado é categorizado como um dígito decimal.

IsLetter(Rune)

Retorna um valor que indica se o rune especificado é categorizado como uma letra.

IsLetterOrDigit(Rune)

Retorna um valor que indica se o rune especificado é categorizado como uma letra ou um dígito decimal.

IsLower(Rune)

Retorna um valor que indica se o rune especificado é categorizado como uma letra minúscula.

IsNumber(Rune)

Retorna um valor que indica se o rune especificado é categorizado como um número.

IsPunctuation(Rune)

Retorna um valor que indica se o rune especificado é categorizado como uma marca de pontuação.

IsSeparator(Rune)

Retorna um valor que indica se o rune especificado é categorizado como um caractere separador.

IsSymbol(Rune)

Retorna um valor que indica se o rune especificado é categorizado como um caractere de símbolo.

IsUpper(Rune)

Retorna um valor que indica se o rune especificado é categorizado como uma letra maiúscula.

IsValid(Int32)

Retorna um valor que indica se um inteiro com sinal de 32 bits representa um valor escalar Unicode válido; ou seja, está no intervalo [ U+0000..U+D7FF ], inclusive; ou [ U+E000.. U+10FFFF ], inclusive.

IsValid(UInt32)

Retorna um valor que indica se um inteiro sem sinal de 32 bits representa um valor escalar Unicode válido; ou seja, está no intervalo [ U+0000..U+D7FF ], inclusive ou [ U+E000.. U+10FFFF ], inclusive.

IsWhiteSpace(Rune)

Retorna um valor que indica se o rune especificado é categorizado como um caractere de espaço em branco.

ToLower(Rune, CultureInfo)

Retorna uma cópia do especificado Rune convertido em minúsculas, usando as regras de maiúsculas e minúsculas da cultura especificada.

ToLowerInvariant(Rune)

Retorna uma cópia do especificado Rune convertido em minúsculas usando as regras de maiúsculas e minúsculas da cultura invariável.

ToString()

Retorna a representação de cadeia de caracteres dessa Rune instância.

ToUpper(Rune, CultureInfo)

Retorna uma cópia do especificado Rune convertido em maiúsculas, usando as regras de maiúsculas da cultura especificada.

ToUpperInvariant(Rune)

Retorna uma cópia do especificado Rune convertido em maiúsculas usando as regras de maiúsculas da cultura invariável.

TryCreate(Char, Char, Rune)

Tenta criar um Rune do par alternativo UTF-16 especificado e retorna um valor que indica se a operação foi bem-sucedida.

TryCreate(Char, Rune)

Tenta criar um Rune de um caractere especificado e retorna um valor que indica se a operação foi bem-sucedida.

TryCreate(Int32, Rune)

Tenta criar um Rune inteiro com sinal especificado que representa um valor escalar Unicode.

TryCreate(UInt32, Rune)

Tenta criar um Rune inteiro sem sinal de 32 bits especificado que representa um valor escalar Unicode.

TryEncodeToUtf16(Span<Char>, Int32)

Codifica isso Rune em um buffer de destino codificado em UTF-16.

TryEncodeToUtf8(Span<Byte>, Int32)

Codifica isso Rune em um buffer de destino codificado em UTF-8.

TryGetRuneAt(String, Int32, Rune)

Tenta obter o Rune que começa em uma posição especificada em uma cadeia de caracteres e retornar um valor que indica se a operação foi bem-sucedida.

Operadores

Nome Description
Equality(Rune, Rune)

Retorna um valor que indica se duas Rune instâncias são iguais.

Explicit(Char to Rune)

Define uma conversão explícita de um caractere Unicode de 16 bits em um Rune.

Explicit(Int32 to Rune)

Define uma conversão explícita de um inteiro com sinal de 32 bits em um Rune.

Explicit(UInt32 to Rune)

Define uma conversão explícita de um inteiro sem sinal de 32 bits em um Rune.

GreaterThan(Rune, Rune)

Retorna um valor que indica se um especificado Rune é maior que outro especificado Rune.

GreaterThanOrEqual(Rune, Rune)

Retorna um valor que indica se um especificado Rune é maior ou igual a outro especificado Rune.

Inequality(Rune, Rune)

Retorna um valor que indica se duas Rune instâncias têm valores diferentes.

LessThan(Rune, Rune)

Retorna um valor que indica se um especificado Rune é menor que outro especificado Rune.

LessThanOrEqual(Rune, Rune)

Retorna um valor que indica se um especificado Rune é menor ou igual a outro especificado Rune.

Implantações explícitas de interface

Nome Description
IComparable.CompareTo(Object)

Compara a instância atual com o objeto especificado.

IFormattable.ToString(String, IFormatProvider)

Formata o valor da instância atual usando o formato especificado.

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

Tenta formatar o valor da instância atual no intervalo de caracteres fornecido.

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

Tenta formatar o valor da instância atual como UTF-8 no intervalo de bytes fornecido.

IUtf8SpanParsable<Rune>.Parse(ReadOnlySpan<Byte>, IFormatProvider)

Analisa um intervalo de caracteres UTF-8 em um valor.

IUtf8SpanParsable<Rune>.TryParse(ReadOnlySpan<Byte>, IFormatProvider, Rune)

Representa um valor escalar Unicode ([ U+0000.U+D7FF ], inclusive; ou [ U+E000.. U+10FFFF ], inclusive).

Aplica-se a