Rune Struktura

Definice

Představuje skalární hodnotu Unicode ([ U+0000..U+D7FF ], inclusive; nebo [ U+E000.. U+10FFFF ], včetně).

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 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<System.Text.Rune>, IEquatable<System.Text.Rune>
type Rune = struct
type Rune = struct
    interface ISpanFormattable
    interface IFormattable
type Rune = struct
    interface IFormattable
    interface ISpanFormattable
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)
Dědičnost
Implementuje

Poznámky

Rune Instance představuje skalární hodnotu Unicode, což znamená jakýkoli bod kódu s výjimkou náhradního rozsahu (U+D800.). U+DFFF). Konstruktory typu a operátory převodu ověřují vstup, takže uživatelé můžou volat rozhraní API za předpokladu, že je základní Rune instance dobře vytvořena.

Pokud neznáte termíny Skalární hodnota Unicode, bod kódu, náhradní oblast a dobře formátovaná oblast, přečtěte si článek Úvod k kódování znaků v .NET.

Následující části vysvětlují:

Kdy použít typ Rune

Pokud kód používáte, Rune zvažte použití typu:

  • Volá rozhraní API, která vyžadují skalární hodnoty Unicode.
  • Explicitně zpracovává náhradní páry.

Rozhraní API, která vyžadují skalární hodnoty Unicode

Pokud váš kód iteruje char instancemi v string nebo a ReadOnlySpan<char>, některé z char metod nebudou správně fungovat na char instancích, které jsou v náhradním rozsahu. Například následující rozhraní API vyžadují, aby skalární hodnota char fungovala správně:

Následující příklad ukazuje kód, který nebude fungovat správně, pokud některé z char instancí jsou náhradní body kódu:

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

Tady je ekvivalentní kód, který funguje s 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;
}

Předchozí kód funguje správně s některými jazyky, jako je angličtina:

CountLettersInString("Hello")
// Returns 5

Ale nebude fungovat správně pro jazyky mimo základní vícejazyčnou rovinu, například Osage:

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

Důvodem, proč tato metoda vrátí nesprávné výsledky textu Osage je, že char instance písmen Osage jsou náhradní body kódu. Žádný náhradní bod kódu nemá dostatek informací k určení, jestli jde o dopis.

Pokud tento kód změníte tak, aby se místo chartoho používalRune, funguje metoda správně s body kódu mimo základní vícejazyčnou rovinu:

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

Tady je ekvivalentní kód, který funguje s ReadOnlySpan<char>:

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

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

    return letterCount;
}

Předchozí kód správně počítá písmena Osage:

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

Kód, který explicitně zpracovává náhradní páry

Zvažte použití Rune typu, pokud váš kód volá rozhraní API, která explicitně pracují s náhradními body kódu, například následující metody:

Například následující metoda má zvláštní logiku pro řešení náhradních char párů:

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.");
        }
    }
}

Tento kód je jednodušší, pokud používá Rune, jako v následujícím příkladu:

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

Kdy se nepoužívá Rune

Pokud kód používáte, nemusíte tento typ používat Rune :

  • Hledá přesnou char shodu.
  • Rozdělí řetězec na známou hodnotu znaku.

Rune Použití typu může vracet nesprávné výsledky, pokud kód:

  • Spočítá počet zobrazených znaků v string

Vyhledání přesných char shod

Následující kód iteruje hledáním string konkrétních znaků a vrátí index první shody. Tento kód není potřeba změnit tak, aby používal Rune, protože kód hledá znaky, které jsou reprezentovány jedním 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
}

Rozdělení řetězce na známé char

Běžně se volat string.Split a používat oddělovače, jako ' ' je (mezera) nebo ',' (čárka), jak je znázorněno v následujícím příkladu:

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

Zde není nutné použít Rune , protože kód hledá znaky, které jsou reprezentovány jedním char.

Spočítejte počet zobrazených znaků v string

Počet Rune instancí v řetězci nemusí odpovídat počtu uživatelsky srozumitelných znaků zobrazených při zobrazení řetězce.

Vzhledem k tomu, že Rune instance představují skalární hodnoty Unicode, můžou komponenty, které dodržují pokyny pro segmentaci textu Unicode , použít Rune jako stavební blok pro počítání zobrazených znaků.

Typ StringInfo lze použít k počítání zobrazených znaků, ale ve všech scénářích jiných než .NET 5+ se počítá správně.

Další informace najdete v tématu Clustery Grapheme.

Jak vytvořit instanci Rune

Existuje několik způsobů, jak získat Rune instanci. Konstruktor můžete použít k vytvoření Rune přímo z:

  • Bod kódu.

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

    Rune c = new Rune('a');
    
  • Náhradní char pár.

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

Všechny konstruktory vyvolá, ArgumentException pokud vstup nepředstavuje platnou skalární hodnotu Unicode.

Rune.TryCreate Existují metody pro volající, kteří nechtějí, aby výjimky byly vyvoláni selháním.

Rune Instance lze také číst z existujících vstupních sekvencí. Například vzhledem ReadOnlySpan<char> k tomu, že představuje data UTF-16, Rune.DecodeFromUtf16 metoda vrátí první Rune instanci na začátku vstupního rozsahu. Metoda Rune.DecodeFromUtf8 funguje podobně a přijímá ReadOnlySpan<byte> parametr, který představuje data UTF-8. Existují ekvivalentní metody pro čtení od konce rozsahu místo začátku rozsahu.

Vlastnosti dotazu objektu a Rune

Pokud chcete získat celočíselnou hodnotu Rune bodu kódu instance, použijte Rune.Value vlastnost.

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

Řada statických rozhraní API dostupných pro char daný typ je také k dispozici pro Rune daný typ. Například Rune.IsWhiteSpace a Rune.GetUnicodeCategory jsou ekvivalenty a Char.IsWhiteSpace Char.GetUnicodeCategory metody. Metody Rune správně zpracovávají náhradní páry.

Následující ukázkový kód přebírá ReadOnlySpan<char> jako vstup a ořízne od začátku i na konec rozsahu, Rune který není písmenem nebo číslicí.

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

Mezi rozhraním API char a Rune. Například:

Rune Převod na UTF-8 nebo UTF-16

Rune Vzhledem k tomu, že je skalární hodnota Unicode, lze ji převést na kódování UTF-8, UTF-16 nebo UTF-32. Typ Rune má integrovanou podporu převodu na UTF-8 a UTF-16.

Rune Převede Rune.EncodeToUtf16 instanci na char instance. Chcete-li dotazovat počet char instancí, které by výsledkem převodu Rune instance na UTF-16, použijte Rune.Utf16SequenceLength vlastnost. Podobné metody existují pro převod UTF-8.

Následující příklad převede Rune instanci na char pole. Kód předpokládá, že máte Rune v rune proměnné instanci:

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

Vzhledem k tomu, že string je posloupnost znaků UTF-16, následující příklad také převede Rune instanci na UTF-16:

string theString = rune.ToString();

Následující příklad převede Rune instanci na bajtové UTF-8 pole:

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

Rune.EncodeToUtf8 Metody Rune.EncodeToUtf16 vrátí skutečný počet zapsaných prvků. Vyvolá výjimku, pokud je cílová vyrovnávací paměť příliš krátká, aby obsahovala výsledek. Volajícím, kteří se chtějí vyhnout výjimkám, existují i metody, které nevyvolávají TryEncodeToUtf8 EncodeToUtf16 .

Spuštění v .NET a jiných jazycích

Termín "rune" není definován ve standardu Unicode. Termín se datuje zpět k vytvoření UTF-8. Rob Pike a Ken Thompson hledali termín, který by se nakonec stal známým jako kódový bod. Uspořádali se s termínem "rune" a Rob Pike později vliv na programovací jazyk Go pomohl pojmem popularizovat.

Typ .NET Rune však není ekvivalentem typu Go rune . V Go je rune typ aliasem pro int32. Rune Go je určen k reprezentaci bodu kódu Unicode, ale může to být libovolná 32bitová hodnota, včetně náhradních bodů kódu a hodnot, které nejsou právními body kódu Unicode.

Podobné typy v jiných programovacích jazycích najdete v primitivním typu rustu char nebo typu SwiftUnicode.Scalar, z nichž obě představují skalární hodnoty Unicode. Poskytují funkce podobné funkci . Rune Typ net a zakáže vytváření instancí hodnot, které nejsou právními skalárními hodnotami Unicode.

Konstruktory

Rune(Char)

Rune Vytvoří z poskytnuté jednotky kódu UTF-16.

Rune(Char, Char)

Rune Vytvoří z poskytnuté dvojice UTF-16 náhradní.

Rune(Int32)

Rune Vytvoří ze zadaného 32bitového celého čísla, které představuje skalární hodnotu Unicode.

Rune(UInt32)

Rune Vytvoří ze zadaného 32bitového celočíselného bez znaménka, které představuje skalární hodnotu Unicode.

Vlastnosti

IsAscii

Získá hodnotu, která označuje, zda skalární hodnota přidružená k tomuto Rune je v rozsahu kódování ASCII.

IsBmp

Získá hodnotu, která označuje, zda skalární hodnota přidružená k tomuto Rune je v rozsahu kódování BMP.

Plane

Získá rovinu Unicode (0 až 16 včetně), která obsahuje tento skalární.

ReplacementChar

Rune Získá instanci, která představuje náhradní znak Unicode U+FFFD.

Utf16SequenceLength

Získá délku v jednotkách kódu (Char) sekvence UTF-16 vyžadované k reprezentaci této skalární hodnoty.

Utf8SequenceLength

Získá délku v jednotkách kódu sekvence UTF-8 vyžadované k reprezentaci této skalární hodnoty.

Value

Získá skalární hodnotu Unicode jako celé číslo.

Metody

CompareTo(Rune)

Porovná aktuální instanci se zadanou Rune instancí.

DecodeFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Dekóduje Rune na začátku poskytnuté zdrojové vyrovnávací paměti UTF-16.

DecodeFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Dekóduje Rune na začátku poskytnuté zdrojové vyrovnávací paměti UTF-8.

DecodeLastFromUtf16(ReadOnlySpan<Char>, Rune, Int32)

Dekóduje Rune na konci poskytnuté zdrojové vyrovnávací paměti UTF-16.

DecodeLastFromUtf8(ReadOnlySpan<Byte>, Rune, Int32)

Dekóduje Rune na konci poskytnuté zdrojové vyrovnávací paměti UTF-8.

EncodeToUtf16(Span<Char>)

Kóduje to Rune do cílové vyrovnávací paměti UTF-16.

EncodeToUtf8(Span<Byte>)

Kóduje to Rune do cílové vyrovnávací paměti UTF-8.

Equals(Object)

Vrátí hodnotu, která označuje, zda se aktuální instance a zadaný objekt rovná.

Equals(Rune)

Vrátí hodnotu, která označuje, jestli se aktuální instance a zadaná rune rovná.

GetHashCode()

Vrátí hodnotu hash pro tuto instanci.

GetNumericValue(Rune)

Získá číselnou hodnotu přidruženou k zadanému rune.

GetRuneAt(String, Int32)

Rune Získá ten, který začíná na zadané pozici v řetězci.

GetUnicodeCategory(Rune)

Získá kategorii Unicode přidruženou k zadané rune.

IsControl(Rune)

Vrátí hodnotu, která označuje, jestli je zadaný rune zařazen do kategorií jako řídicí znak.

IsDigit(Rune)

Vrátí hodnotu, která označuje, jestli je zadaný rune zařazen do kategorií jako desetinná číslice.

IsLetter(Rune)

Vrátí hodnotu, která označuje, zda je zadaný rune zařazen do kategorií jako písmeno.

IsLetterOrDigit(Rune)

Vrátí hodnotu, která označuje, zda je zadaný rune zařazen do kategorií jako písmeno nebo desetinná číslice.

IsLower(Rune)

Vrátí hodnotu, která označuje, zda je zadaný rune zařazen do kategorií jako malá písmena.

IsNumber(Rune)

Vrátí hodnotu, která označuje, jestli je zadaný rune zařazen do kategorií jako číslo.

IsPunctuation(Rune)

Vrátí hodnotu, která označuje, jestli je zadaný rune zařazený do kategorií jako interpunkční znaménko.

IsSeparator(Rune)

Vrátí hodnotu, která označuje, jestli je zadaný rune zařazen do kategorií jako znak oddělovače.

IsSymbol(Rune)

Vrátí hodnotu, která označuje, jestli je zadaný rune zařazen do kategorií jako znak symbolu.

IsUpper(Rune)

Vrátí hodnotu, která označuje, zda je zadaný rune zařazen do kategorií jako velká písmena.

IsValid(Int32)

Vrátí hodnotu, která označuje, zda 32bitové celé číslo podepsaného představuje platnou skalární hodnotu Unicode; to znamená, že je v rozsahu [ U+0000..U+D7FF ], včetně; nebo [ U+E000.. U+10FFFF ], včetně.

IsValid(UInt32)

Vrátí hodnotu, která označuje, jestli 32bitové celé číslo bez znaménka představuje platnou skalární hodnotu Unicode; to znamená, že je v rozsahu [ U+0000..U+D7FF ], včetně nebo [ U+E000.. U+10FFFF ], včetně.

IsWhiteSpace(Rune)

Vrátí hodnotu, která označuje, zda je zadaný rune zařazen do kategorií jako prázdný znak.

ToLower(Rune, CultureInfo)

Vrátí kopii zadané Rune převedené na malá písmena pomocí pravidel pro velikost písmen zadané jazykové verze.

ToLowerInvariant(Rune)

Vrátí kopii zadané Rune převedené na malá písmena pomocí pravidel pro velká písmena invariantní jazykové verze.

ToString()

Vrátí řetězcovou reprezentaci této Rune instance.

ToUpper(Rune, CultureInfo)

Vrátí kopii zadaného Rune převedeného na velká písmena pomocí pravidel pro velká písmena zadané jazykové verze.

ToUpperInvariant(Rune)

Vrátí kopii zadané Rune převedené na velká písmena pomocí pravidel pro velká písmena invariantní jazykové verze.

TryCreate(Char, Char, Rune)

Pokusí se vytvořit Rune ze zadaného náhradního páru UTF-16 a vrátí hodnotu, která označuje, jestli byla operace úspěšná.

TryCreate(Char, Rune)

Pokusí se vytvořit Rune ze zadaného znaku hodnotu, která označuje, jestli operace proběhla úspěšně.

TryCreate(Int32, Rune)

Pokusí se vytvořit Rune ze zadaného podepsaného celého čísla, které představuje skalární hodnotu Unicode.

TryCreate(UInt32, Rune)

Pokusí se vytvořit Rune ze zadaného 32bitového celého čísla bez znaménka, které představuje skalární hodnotu Unicode.

TryEncodeToUtf16(Span<Char>, Int32)

Zakóduje to Rune do cílové vyrovnávací paměti kódování UTF-16.

TryEncodeToUtf8(Span<Byte>, Int32)

Zakóduje to Rune do cílové vyrovnávací paměti kódování UTF-8.

TryGetRuneAt(String, Int32, Rune)

Pokusí se získat Rune hodnotu, která začíná na zadané pozici v řetězci, a vrátí hodnotu, která označuje, zda operace byla úspěšná.

Operátory

Equality(Rune, Rune)

Vrátí hodnotu, která označuje, jestli jsou dvě Rune instance stejné.

Explicit(Char to Rune)

Definuje explicitní převod 16bitového znaku RuneUnicode na znak .

Explicit(Int32 to Rune)

Definuje explicitní převod 32bitového signtegeru na Rune.

Explicit(UInt32 to Rune)

Definuje explicitní převod 32bitového celočíselného celočíselného čísla na Rune.

GreaterThan(Rune, Rune)

Vrátí hodnotu určující, zda je zadaná Rune hodnota větší než jiná zadaná Rune.

GreaterThanOrEqual(Rune, Rune)

Vrátí hodnotu označující, zda je zadaná Rune hodnota větší nebo rovna jinému zadanému .Rune

Inequality(Rune, Rune)

Vrátí hodnotu, která označuje, jestli mají dvě Rune instance různé hodnoty.

LessThan(Rune, Rune)

Vrátí hodnotu označující, zda je zadaná Rune hodnota menší než jiná zadaná Runehodnota .

LessThanOrEqual(Rune, Rune)

Vrátí hodnotu označující, zda je zadaná Rune hodnota menší nebo rovna jiné zadané hodnotě Rune.

Explicitní implementace rozhraní

IComparable.CompareTo(Object)

Porovná aktuální instanci se zadaným objektem.

IFormattable.ToString(String, IFormatProvider)

Formátuje hodnotu aktuální instance pomocí zadaného formátu.

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

Pokusí se naformátovat hodnotu aktuální instance do zadaného rozsahu znaků.

Platí pro