Rune Estructura

Definición

Representa un valor escalar Unicode ([ U+0000..U+D7FF ], inclusive; o [ 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)
Herencia
Implementaciones

Comentarios

Una Rune instancia representa un valor escalar Unicode, lo que significa cualquier punto de código excepto el intervalo de sustitución (U+D800..U+DFFF). Los constructores y operadores de conversión del tipo validan la entrada, por lo que los consumidores pueden llamar a las API suponiendo que la instancia subyacente Rune esté bien formada.

Si no está familiarizado con los términos valor escalar Unicode, punto de código, rango sustituto y bien formado, consulte Introducción a la codificación de caracteres en .NET.

Cuándo usar el tipo Rune

Considere la posibilidad de usar el tipo Rune si tu código:

  • Llama a las API que requieren valores escalares Unicode.
  • Controla explícitamente los pares sustitutos

API que requieren valores escalares Unicode

Si el código recorre las instancias de char en un string o un ReadOnlySpan<char>, algunos métodos de char no funcionarán correctamente en las instancias de char que se encuentran en el rango suplente. Por ejemplo, las siguientes API requieren un valor escalar char para funcionar correctamente.

En el ejemplo siguiente se muestra el código que no funcionará correctamente si alguna de las char instancias son puntos de código suplentes:

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

Este es el código equivalente que funciona con :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;
}

El código anterior funciona correctamente con algunos idiomas como inglés:

CountLettersInString("Hello")
// Returns 5

Pero no funcionará correctamente para idiomas fuera del plano multilingüe básico, como Osage:

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

La razón por la que este método devuelve resultados incorrectos para el texto de Osage es que las char instancias de letras de Osage son puntos de código suplentes. Ningún punto de código suplente único tiene suficiente información para determinar si es una letra.

Si cambia este código para usar Rune en lugar de char, el método funciona correctamente con puntos de código fuera del Plano Multilingüe 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

Este es el código equivalente que funciona con :ReadOnlySpan<char>

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

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

    return letterCount;
}

El código anterior cuenta correctamente las letras de Osage:

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

Código que controla explícitamente pares suplentes

Considere la posibilidad de usar el tipo Rune si su código llama a las API que operan explícitamente en puntos de código sustitutos, como los siguientes métodos:

Por ejemplo, el método siguiente tiene lógica especial para tratar con pares suplentes 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.");
        }
    }
}

Este código es más sencillo si usa Rune, como en el ejemplo siguiente:

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

Cuándo no usar Rune

No es necesario usar el Rune tipo si el código:

  • Busca coincidencias exactas char
  • Divide una cadena en un valor char conocido.

El uso del Rune tipo puede devolver resultados incorrectos si el código:

  • Cuenta el número de caracteres de pantalla en una string

Buscar coincidencias exactas char

El código siguiente recorre una string buscando caracteres específicos y devuelve el índice de la primera coincidencia. No es necesario cambiar este código para usar Rune, ya que el código busca caracteres representados por un ú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
}

Divide una cadena en un char conocido

Es habitual llamar string.Split a y usar delimitadores como ' ' (espacio) o ',' (coma), como en el ejemplo siguiente:

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

No es necesario usar Rune aquí, ya que el código busca caracteres representados por un solo char.

Cuenta el número de caracteres de pantalla en una string

Es posible que el número de instancias de Rune una cadena no coincida con el número de caracteres reconocibles por el usuario que se muestran al mostrar la cadena.

Dado que las instancias Rune representan valores escalares Unicode, los componentes que siguen las instrucciones de segmentación de texto Unicode pueden usar Rune como bloque de construcción para contar caracteres para mostrar.

El StringInfo tipo se puede usar para contar caracteres de pantalla, pero no cuenta correctamente en todas las implementaciones de .NET distintas de .NET 5+.

Para más información, consulte Clústeres de Grapheme.

Cómo instanciar un Rune

Hay varias maneras de obtener una Rune instancia. Puede usar un constructor para crear un Rune directamente desde:

  • Un punto de código.

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

    Rune c = new Rune('a');
    
  • Un par char suplente.

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

Todos los constructores lanzan un ArgumentException si la entrada no representa un valor escalar Unicode válido.

Hay métodos Rune.TryCreate disponibles para los autores de llamada que no quieren que se produzcan excepciones en caso de error.

Rune Las instancias también se pueden leer de secuencias de entrada existentes. Por ejemplo, dado un ReadOnlySpan<char> que representa datos UTF-16, el Rune.DecodeFromUtf16 método devuelve la primera Rune instancia al principio del intervalo de entrada. El Rune.DecodeFromUtf8 método funciona de forma similar, aceptando un ReadOnlySpan<byte> parámetro que representa datos UTF-8. Existen métodos equivalentes para leer desde el final del intervalo en vez de desde el principio.

Consultar propiedades de un Rune

Para obtener el valor de punto de código entero de una Rune instancia, use la Rune.Value propiedad .

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

Muchas de las API estáticas disponibles en el char tipo también están disponibles en el Rune tipo . Por ejemplo, Rune.IsWhiteSpace y Rune.GetUnicodeCategory son equivalentes a los métodos Char.IsWhiteSpace y Char.GetUnicodeCategory. Los Rune métodos controlan correctamente los pares suplentes.

El siguiente código de ejemplo toma un ReadOnlySpan<char> como entrada y recorta, desde el principio y el final del intervalo, todo Rune que no sea una letra o un 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;
}

Hay algunas diferencias de API entre char y Rune. Por ejemplo:

Convertir un Rune a UTF-8 o UTF-16

Dado que es Rune un valor escalar Unicode, se puede convertir en codificación UTF-8, UTF-16 o UTF-32. El Rune tipo tiene compatibilidad integrada para la conversión a UTF-8 y UTF-16.

Rune.EncodeToUtf16 convierte una Rune instancia en char instancias. Para consultar el número de instancias de char que resultarían al convertir una instancia de Rune a UTF-16, use la propiedad Rune.Utf16SequenceLength. Existen métodos similares para la conversión UTF-8.

En el ejemplo siguiente se convierte una Rune instancia en una char matriz. El código supone que tiene una Rune instancia en la rune variable :

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

Dado que es string una secuencia de caracteres UTF-16, el ejemplo siguiente también convierte una Rune instancia en UTF-16:

string theString = rune.ToString();

En el ejemplo siguiente se convierte una Rune instancia en una matriz de UTF-8 bytes:

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

Los Rune.EncodeToUtf16 métodos y Rune.EncodeToUtf8 devuelven el número real de elementos escritos. Generan una excepción si el búfer de destino es demasiado corto para contener el resultado. Hay métodos TryEncodeToUtf8 y TryEncodeToUtf16 que no lanzan excepciones, para aquellos que desean evitar excepciones al llamar.

Rune en .NET frente a otros lenguajes

El término "rune" no se define en el estándar Unicode. El término se remonta a la creación de UTF-8. Rob Pike y Ken Thompson buscaban un término para describir lo que finalmente se conocería como punto de código. Se establecieron en el término "rune", y la influencia posterior de Rob Pike sobre el lenguaje de programación Go ayudó a popularizar el término.

Sin embargo, el tipo de .NET Rune no es el equivalente del tipo Go rune . En Go, el rune tipo es un alias para int32. Un rune de Go está diseñado para representar un punto de código Unicode, pero puede ser cualquier valor de 32 bits, incluidos los puntos de código suplentes y los valores que no son puntos de código Unicode legales.

Para ver tipos similares en otros lenguajes de programación, consulte El tipo primitivo char de Rust o el tipo de SwiftUnicode.Scalar, ambos representan valores escalares Unicode. Proporcionan una funcionalidad similar al tipo Rune de .NET y no permiten la creación de instancias de valores que no son valores Unicode escalares válidos.

Constructores

Nombre Description
Rune(Char, Char)

Crea un Rune objeto a partir del par suplente UTF-16 proporcionado.

Rune(Char)

Crea un Rune objeto a partir de la unidad de código UTF-16 proporcionada.

Rune(Int32)

Crea un Rune objeto a partir del entero de 32 bits especificado que representa un valor escalar Unicode.

Rune(UInt32)

Crea a Rune partir del entero de 32 bits sin signo especificado que representa un valor escalar Unicode.

Propiedades

Nombre Description
IsAscii

Obtiene un valor que indica si el valor escalar asociado a esto Rune está dentro del intervalo de codificación ASCII.

IsBmp

Obtiene un valor que indica si el valor escalar asociado a esto Rune está dentro del intervalo de codificación BMP.

Plane

Obtiene el plano Unicode (de 0 a 16, ambos incluidos) que contiene este escalar.

ReplacementChar

Obtiene una Rune instancia que representa el carácter de reemplazo Unicode U+FFFD.

Utf16SequenceLength

Obtiene la longitud de las unidades de código (Char) de la secuencia UTF-16 necesaria para representar este valor escalar.

Utf8SequenceLength

Obtiene la longitud de las unidades de código de la secuencia UTF-8 necesaria para representar este valor escalar.

Value

Obtiene el valor escalar Unicode como un entero.

Métodos

Nombre Description
CompareTo(Rune)

Compara la instancia actual con la instancia especificada Rune .

DecodeFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Descodifica al Rune principio del búfer de origen UTF-16 proporcionado.

DecodeFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Descodifica al Rune principio del búfer de origen UTF-8 proporcionado.

DecodeLastFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Descodifica al Rune final del búfer de origen UTF-16 proporcionado.

DecodeLastFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Descodifica al Rune final del búfer de origen UTF-8 proporcionado.

EncodeToUtf16(Span<Char>)

Codifica esto Rune en un búfer de destino UTF-16.

EncodeToUtf8(Span<Byte>)

Codifica esto Rune en un búfer de destino UTF-8.

Equals(Object)

Devuelve un valor que indica si la instancia actual y un objeto especificado son iguales.

Equals(Rune, StringComparison)

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

Equals(Rune)

Devuelve un valor que indica si la instancia actual y un rune especificado son iguales.

GetHashCode()

Devuelve el código hash de esta instancia.

GetNumericValue(Rune)

Obtiene el valor numérico asociado al rune especificado.

GetRuneAt(String, Int32)

Obtiene el Rune objeto que comienza en una posición especificada de una cadena.

GetUnicodeCategory(Rune)

Obtiene la categoría Unicode asociada al rune especificado.

IsControl(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como un carácter de control.

IsDigit(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como un dígito decimal.

IsLetter(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como una letra.

IsLetterOrDigit(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como una letra o un dígito decimal.

IsLower(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como una letra minúscula.

IsNumber(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como un número.

IsPunctuation(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como signo de puntuación.

IsSeparator(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como carácter separador.

IsSymbol(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como un carácter de símbolo.

IsUpper(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como una letra mayúscula.

IsValid(Int32)

Devuelve un valor que indica si un entero de 32 bits con signo representa un valor escalar Unicode válido; es decir, está en el intervalo [ U+0000..U+D7FF ], inclusive; o [ U+E000.. U+10FFFF ], inclusive.

IsValid(UInt32)

Devuelve un valor que indica si un entero de 32 bits sin signo representa un valor escalar Unicode válido; es decir, está en el intervalo [ U+0000..U+D7FF ], inclusive, o [ U+E000.. U+10FFFF ], inclusive.

IsWhiteSpace(Rune)

Devuelve un valor que indica si el rune especificado se clasifica como un carácter de espacio en blanco.

ToLower(Rune, CultureInfo)

Devuelve una copia del especificado Rune convertido en minúsculas mediante las reglas de mayúsculas y minúsculas de la referencia cultural especificada.

ToLowerInvariant(Rune)

Devuelve una copia del especificado Rune convertido en minúsculas mediante las reglas de mayúsculas y minúsculas de la referencia cultural invariable.

ToString()

Devuelve la representación de cadena de esta Rune instancia.

ToUpper(Rune, CultureInfo)

Devuelve una copia del especificado Rune convertido en mayúsculas mediante las reglas de mayúsculas de la referencia cultural especificada.

ToUpperInvariant(Rune)

Devuelve una copia del especificado Rune convertido en mayúsculas mediante las reglas de mayúsculas de la referencia cultural invariable.

TryCreate(Char, Char, Rune)

Intenta crear un Rune a partir del par suplente UTF-16 especificado y devuelve un valor que indica si la operación se realizó correctamente.

TryCreate(Char, Rune)

Intenta crear un Rune a partir de un carácter especificado y devuelve un valor que indica si la operación se realizó correctamente.

TryCreate(Int32, Rune)

Intenta crear a Rune partir de un entero con signo especificado que representa un valor escalar Unicode.

TryCreate(UInt32, Rune)

Intenta crear a Rune partir del entero de 32 bits sin signo especificado que representa un valor escalar Unicode.

TryEncodeToUtf16(Span<Char>, Int32)

Codifica esto Rune en un búfer de destino codificado UTF-16.

TryEncodeToUtf8(Span<Byte>, Int32)

Codifica esto Rune en un búfer de destino codificado UTF-8.

TryGetRuneAt(String, Int32, Rune)

Intenta obtener el Rune que comienza en una posición especificada en una cadena y devuelve un valor que indica si la operación se realizó correctamente.

Operadores

Nombre Description
Equality(Rune, Rune)

Devuelve un valor que indica si dos Rune instancias son iguales.

Explicit(Char to Rune)

Define una conversión explícita de un carácter Unicode de 16 bits a .Rune

Explicit(Int32 to Rune)

Define una conversión explícita de un entero de 32 bits con signo en .Rune

Explicit(UInt32 to Rune)

Define una conversión explícita de un entero de 32 bits sin signo en un Rune.

GreaterThan(Rune, Rune)

Devuelve un valor que indica si un especificado Rune es mayor que otro especificado Rune.

GreaterThanOrEqual(Rune, Rune)

Devuelve un valor que indica si un especificado Rune es mayor o igual que otro especificado Rune.

Inequality(Rune, Rune)

Devuelve un valor que indica si dos Rune instancias tienen valores diferentes.

LessThan(Rune, Rune)

Devuelve un valor que indica si un especificado Rune es menor que otro especificado Rune.

LessThanOrEqual(Rune, Rune)

Devuelve un valor que indica si un objeto especificado Rune es menor o igual que otro especificado Rune.

Implementaciones de interfaz explícitas

Nombre Description
IComparable.CompareTo(Object)

Compara la instancia actual con el objeto especificado.

IFormattable.ToString(String, IFormatProvider)

Da formato al valor de la instancia actual mediante el formato especificado.

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

Intenta dar formato al valor de la instancia actual en el intervalo de caracteres proporcionado.

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

Intenta dar formato al valor de la instancia actual como UTF-8 en el intervalo de bytes proporcionado.

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

Analiza un intervalo de caracteres UTF-8 en un valor.

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

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

Se aplica a