Sdílet prostřednictvím


Řetězce a řetězcové literály

Řetězec je objekt typu String jehož hodnota je text. Interně je text ukládán jako sekvenční kolekce objektů Char určená pouze pro čtení. Vlastnost Length řetězce představuje počet Char objektů, které obsahuje, nikoli počet znaků Unicode. Pokud chcete získat přístup k jednotlivým bodům kódu Unicode v řetězci, použijte StringInfo objekt.

string vs. System.String

V jazyce C# je klíčové slovo string aliasem pro String; proto jsou String a string ekvivalentní. Použijte zadaný alias string, protože funguje i bez using System;. Třída String poskytuje mnoho metod pro bezpečné vytváření, manipulaci s nimi a porovnávání řetězců. Kromě toho jazyk C# přetěžuje některé operátory, aby zjednodušily běžné řetězcové operace. Další informace o klíčovém slově najdete v části řetězec. Další informace o typu a jeho metodách naleznete v tématu String.

Deklarace a inicializace řetězců

Řetězce můžete deklarovat a inicializovat různými způsoby, jak je znázorněno v následujícím příkladu:

// Declare without initializing.
string message1;

// Initialize to null.
string? message2 = null;

// Initialize as an empty string.
// Use the Empty constant instead of the literal "".
string message3 = System.String.Empty;

// Initialize with a regular string literal.
string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0";

// Initialize with a verbatim string literal.
string newPath = @"c:\Program Files\Microsoft Visual Studio 9.0";

// Use System.String if you prefer.
System.String greeting = "Hello World!";

// In local variables (i.e. within a method body)
// you can use implicit typing.
var temp = "I'm still a strongly-typed System.String!";

// Use a const string to prevent 'message4' from
// being used to store another string value.
const string message4 = "You can't get rid of me!";

// Use the String constructor only when creating
// a string from a char*, char[], or sbyte*. See
// System.String documentation for details.
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);

Nepoužíváte nový operátor k vytvoření objektu řetězce, kromě když inicializujete řetězec pomocí pole znaků.

Inicializujte řetězec s Empty jako konstantní hodnotou k vytvoření nového objektu String, který má řetězec o nulové délce. Reprezentace řetězcového literálu pro řetězec nulové délky je "". Inicializací řetězců s hodnotou Empty místo null můžete snížit pravděpodobnost výskytu NullReferenceException. Pomocí statické metody IsNullOrEmpty(String) zkontrolujte hodnotu řetězce před pokusem o jeho přístup.

Neměnnost řetězců

Objekty řetězců jsou neměnné: po vytvoření je nelze změnit. Všechny String metody a operátory jazyka C#, které zdánlivě upravují řetězec, skutečně vrátí výsledky v novém řetězcovém objektu. V následujícím příkladu, když je obsah s1 a s2 zřetězen tak, aby vytvořil jeden řetězec, jsou dva původní řetězce nezměněné. Operátor += vytvoří nový řetězec, který obsahuje sloučený obsah. Tento nový objekt je přiřazen proměnné s1a původní objekt, který byl přiřazen k s1, je uvolněn pro garbage collection, protože na něj žádná jiná proměnná neodkazuje.

string s1 = "A string is more ";
string s2 = "than the sum of its chars.";

// Concatenate s1 and s2. This actually creates a new
// string object and stores it in s1, releasing the
// reference to the original object.
s1 += s2;

System.Console.WriteLine(s1);
// Output: A string is more than the sum of its chars.

Vzhledem k tomu, že modifikace řetězce je ve skutečnosti novým vytvořením řetězce, musíte při vytváření odkazů na řetězce používat opatrnost. Pokud vytvoříte odkaz na řetězec a potom původní řetězec "upravíte", odkaz bude odkazovat na původní objekt místo nového objektu, který byl vytvořen při úpravě řetězce. Toto chování ilustruje následující kód:

string str1 = "Hello ";
string str2 = str1;
str1 += "World";

System.Console.WriteLine(str2);
//Output: Hello

Další informace o tom, jak vytvořit nové řetězce založené na úpravách, jako je vyhledávání a nahrazení operací na původním řetězci, naleznete v tématu Jak upravit obsah řetězce.

Řetězcové literály s uvozovkami

Řetězce v uvozovkách začínají a končí jedním znakem dvojité uvozovky (") na stejném řádku. Řetězcové literály v uvozovkách jsou nejvhodnější pro řetězce, které se vejdou na jeden řádek a neobsahují žádné escapovací sekvence. Řetězcový literál s citacemi musí vkládat řídicí znaky, jak je znázorněno v následujícím příkladu:

string columns = "Column 1\tColumn 2\tColumn 3";
//Output: Column 1        Column 2        Column 3

string rows = "Row 1\r\nRow 2\r\nRow 3";
/* Output:
    Row 1
    Row 2
    Row 3
*/

string title = "\"The \u00C6olean Harp\", by Samuel Taylor Coleridge";
//Output: "The Æolean Harp", by Samuel Taylor Coleridge

Doslovné řetězcové literály

Doslovné řetězcové literály jsou pohodlnější pro víceřádkové řetězce, řetězce obsahující znaky zpětného lomítka nebo obsahující dvojité uvozovky. Doslovné řetězce zachovávají znaky nového řádku jako součást textu řetězce. Pomocí dvojitých uvozovek uveďte uvozovky uvnitř doslovného řetězce. Následující příklad ukazuje některé běžné použití doslovných řetězců:

string title = "\"The \u00C6olean Harp\", by Samuel Taylor Coleridge";
//Output: "The Æolean Harp", by Samuel Taylor Coleridge

string filePath = @"C:\Users\scoleridge\Documents\";
//Output: C:\Users\scoleridge\Documents\

string text = @"My pensive SARA ! thy soft cheek reclined
    Thus on mine arm, most soothing sweet it is
    To sit beside our Cot,...";
/* Output:
My pensive SARA ! thy soft cheek reclined
    Thus on mine arm, most soothing sweet it is
    To sit beside our Cot,...
*/

string quote = @"Her name was ""Sara.""";
//Output: Her name was "Sara."

Nezpracované řetězcové literály

Počínaje jazykem C# 11 můžete použít nezpracované řetězcové literály k snadnějšímu vytváření řetězců, které jsou víceřádkové, nebo můžete použít libovolné znaky vyžadující řídicí sekvence. Syrové řetězcové literály odstraňují potřebu používat escape sekvence kdykoli. Výstup můžete napsat jako řetězec, včetně mezer, přesně tak, jak ho chcete ve výsledku zobrazit. surový literál řetězce:

  • Začíná a končí sekvencí alespoň tří dvojitých uvozovek ("""). K zahájení a ukončení sekvence můžete použít více než tři po sobě jdoucí znaky, které podporují řetězcové literály, které obsahují tři (nebo více) opakovaných uvozovek.
  • Jednořádkové řetězcové literály vyžadují počáteční a uzavírací uvozovky na stejném řádku.
  • Víceřádkové nezpracované řetězcové literály vyžadují otevírací i uzavírací uvozovku na vlastním řádku.
  • V nezpracovaných řetězcových literálech více řádků je jakýkoliv prázdný znak vlevo od uzavíracích uvozovek odstraněn ze všech řádků řetězcového literálu.
  • U víceřádkových řetězcových literálů se prázdné znaky za levou uvozovkou na stejném řádku ignorují.
  • V nezpracovaných víceřádkových řetězcových literálech jsou do řetězcového literálu zahrnuty řádky obsahující pouze bílé znaky, které následují za úvodním uvozovkou.

Následující příklady ukazují tato pravidla:

string singleLine = """Friends say "hello" as they pass by.""";
string multiLine = """
    "Hello World!" is typically the first program someone writes.
    """;
string embeddedXML = """
       <element attr = "content">
           <body style="normal">
               Here is the main text
           </body>
           <footer>
               Excerpts from "An amazing story"
           </footer>
       </element >
       """;
// The line "<element attr = "content">" starts in the first column.
// All whitespace left of that column is removed from the string.

string rawStringLiteralDelimiter = """"
    Raw string literals are delimited 
    by a string of at least three double quotes,
    like this: """
    """";

Následující příklady ukazují chyby kompilátoru hlášené na základě těchto pravidel:

// CS8997: Unterminated raw string literal.
var multiLineStart = """This
    is the beginning of a string 
    """;

// CS9000: Raw string literal delimiter must be on its own line.
var multiLineEnd = """
    This is the beginning of a string """;

// CS8999: Line does not start with the same whitespace as the closing line
// of the raw string literal
var noOutdenting = """
    A line of text.
Trying to outdent the second line.
    """;

První dva příklady jsou neplatné, protože víceřádkové řetězcové literály vyžadují otevírací a uzavírací posloupnost uvozovek na samostatném řádku. Třetí příklad je neplatný, protože text je odsažením od uzavírací sekvence uvozovek.

Pokud generujete text, který obsahuje znaky vyžadující únikové sekvence při použití řetězců uvedených v uvozovkách nebo doslovných řetězců, měli byste zvážit použití nezpracovaných řetězcových literálů. Nezpracované řetězcové literály jsou pro vás a ostatní snadněji čitelné, protože se více podobají výstupnímu textu. Představte si například následující kód, který obsahuje řetězec formátovaného formátu JSON:

string jsonString = """
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "DatesAvailable": [
    "2019-08-01T00:00:00-07:00",
    "2019-08-02T00:00:00-07:00"
  ],
  "TemperatureRanges": {
    "Cold": {
      "High": 20,
      "Low": -10
    },
    "Hot": {
      "High": 60,
      "Low": 20
    }
            },
  "SummaryWords": [
    "Cool",
    "Windy",
    "Humid"
  ]
}
""";

Únikové sekvence v řetězcích

Úniková sekvence Jméno postavy Kódování Unicode
\' Jednoduchá uvozovka 0x0027
\" Dvojitá uvozovka 0x0022
\\ Zpětné lomítko 0x005C
\0 Nula 0x0000
\a Poplach 0x0007
\b Backspace 0x0008
\e Uniknout 0x001B
\f Podávání formuláře 0x000C
\n Nový řádek 0x000A
\r Návrat vozíku 0x000D
\t Horizontální tabulátor 0x0009
\v Svislý tabulátor 0x000B
\u Unikódová escape sekvence (UTF-16) \uHHHH (rozsah: 0000 – FFFF; příklad: \u00E7 = "ç")
\U Unikódová úniková sekvence (UTF-32) \U00HHHHHH (rozsah: 000000 – 10FFFF; příklad: \U0001F47D = "👽")
\x Unikótní sekvence Unicode podobná "\u", ale s proměnlivou délkou. \xH[H][H][H] (rozsah: 0 – FFFF; příklad: \x00E7 nebo \x0E7 nebo \xE7 = "ç")

Varování

Pokud použijete řídicí sekvenci \x a zadáte méně než 4 šestnáctkové číslice, budou-li znaky, které bezprostředně následují za řídicí sekvencí, platné šestnáctkové číslice (tj. 0-9, A-F a a-f), budou interpretovány jako součást řídicí sekvence. Například \xA1 vytvoří "^", což je bod kódu U+00A1. Pokud je ale další znak "A" nebo "a", escape sekvence se místo toho interpretuje jako \xA1A a vytvoří "ਚ", což je kódový bod U+0A1A. V takových případech se zadáním všech 4 šestnáctkových číslic (například \x00A1) zabrání jakékoli možné chybné interpretaci.

Poznámka

V době kompilace se doslovné a nezpracované řetězce převedou na běžné řetězce se všemi stejnými řídicími sekvencemi. Pokud tedy v okně sledování ladicího programu zobrazíte slovníkový nebo surový řetězec, uvidíte escape sekvence přidané kompilátorem, nikoliv jejich slovníkovou nebo surovou verzi ze zdrojového kódu. Například doslovný řetězec @"C:\files.txt" se zobrazí ve sledovacím okně jako "C:\\files.txt".

Formátování řetězců

Formátovací řetězec je řetězec, jehož obsah se dynamicky určuje za běhu. Formátovací řetězce se vytvářejí vložením interpolovaných výrazů nebo zástupných symbolů do složených závorek uvnitř řetězce. Všechno uvnitř složených závorek ({...}) se vyhodnotí na hodnotu a za běhu se zobrazí jako formátovaný řetězec. Existují dvě metody pro vytváření formátových řetězců: interpolace řetězců a složené formátování.

Interpolace řetězců

Deklarujete interpolované řetězce speciálním znakem $. Interpolovaný řetězec obsahuje interpolované výrazy ve složených závorkách. Pokud s interpolací řetězců začínáte, podívejte se na interaktivní kurz Interpolace řetězců – C#, kde najdete rychlý přehled.

Pomocí interpolace řetězců můžete zlepšit čitelnost a udržovatelnost kódu. Interpolace textu dosahuje stejných výsledků jako metoda String.Format, ale usnadňuje použití a zlepšuje srozumitelnost při vkládání.

var jh = (firstName: "Jupiter", lastName: "Hammon", born: 1711, published: 1761);
Console.WriteLine($"{jh.firstName} {jh.lastName} was an African American poet born in {jh.born}.");
Console.WriteLine($"He was first published in {jh.published} at the age of {jh.published - jh.born}.");
Console.WriteLine($"He'd be over {Math.Round((2018d - jh.born) / 100d) * 100d} years old today.");

// Output:
// Jupiter Hammon was an African American poet born in 1711.
// He was first published in 1761 at the age of 50.
// He'd be over 300 years old today.

Interpolaci řetězců můžete použít k inicializaci konstantního řetězce, když všechny výrazy používané pro zástupné symboly jsou také konstantní řetězce.

Počínaje jazykem C# 11 můžete kombinovat nezpracované řetězcové literály s interpolacemi řetězců. Začnete a ukončíte formátovací řetězec třemi nebo více po sobě jdoucími dvojitými uvozovkami. Pokud by měl výstupní řetězec obsahovat { nebo } znak, můžete pomocí dalších $ znaků určit, kolik { a } znaků začíná a končí interpolace. Ve výstupu je zahrnuta jakákoli posloupnost s méně než { nebo } znaky. Následující příklad ukazuje, jak můžete tuto funkci použít k zobrazení vzdálenosti bodu od počátku a umístění bodu do složených závorek:

int X = 2;
int Y = 3;

var pointMessage = $$"""The point {{{X}}, {{Y}}} is {{Math.Sqrt(X * X + Y * Y)}} from the origin.""";

Console.WriteLine(pointMessage);
// Output:
// The point {2, 3} is 3.605551275463989 from the origin.

Doslovné interpolace řetězců

Jazyk C# také umožňuje doslovnou interpolaci řetězců, například přes více řádků, pomocí syntaxe $@ nebo @$.

Chcete-li interpretovat řídicí sekvence doslova, použijte doslovné doslovné řetězcový literál. Interpolovaný doslovný řetězec začíná znakem $ následovaným znakem @. Tokeny $ a @ můžete použít v libovolném pořadí: $@"..." i @$"..." jsou platné doslovné doslovné řetězce.

var jh = (firstName: "Jupiter", lastName: "Hammon", born: 1711, published: 1761);
Console.WriteLine($@"{jh.firstName} {jh.lastName}
    was an African American poet born in {jh.born}.");
Console.WriteLine(@$"He was first published in {jh.published}
at the age of {jh.published - jh.born}.");

// Output:
// Jupiter Hammon
//     was an African American poet born in 1711.
// He was first published in 1761
// at the age of 50.

Složené formátování

String.Format používá zástupné symboly ve křivých závorkách k vytvoření formátového řetězce. Výsledkem tohoto příkladu je podobný výstup jako metoda interpolace řetězců použitá v předchozím vzorku.

var pw = (firstName: "Phillis", lastName: "Wheatley", born: 1753, published: 1773);
Console.WriteLine("{0} {1} was an African American poet born in {2}.", pw.firstName, pw.lastName, pw.born);
Console.WriteLine("She was first published in {0} at the age of {1}.", pw.published, pw.published - pw.born);
Console.WriteLine("She'd be over {0} years old today.", Math.Round((2018d - pw.born) / 100d) * 100d);

// Output:
// Phillis Wheatley was an African American poet born in 1753.
// She was first published in 1773 at the age of 20.
// She'd be over 300 years old today.

Další informace o formátování typů .NET naleznete v tématu Typy formátování v rozhraní .NET.

Podřetězce

Podřetězce je jakákoli posloupnost znaků, která je obsažena v řetězci. Pomocí metody Substring vytvořte nový řetězec z části původního řetězce. Pomocí metody IndexOf můžete vyhledat jeden nebo více výskytů podřetědce. Pomocí metody Replace nahraďte všechny výskyty zadaného podřetězce novým řetězcem. Stejně jako Substring metoda, Replace skutečně vrátí nový řetězec a neupravuje původní řetězec. Další informace naleznete v tématu Jak hledat řetězce a Jak upravit obsah řetězce.

string s3 = "Visual C# Express";
System.Console.WriteLine(s3.Substring(7, 2));
// Output: "C#"

System.Console.WriteLine(s3.Replace("C#", "Basic"));
// Output: "Visual Basic Express"

// Index values are zero-based
int index = s3.IndexOf("C");
// index = 7

Přístup k jednotlivým znakům

Notaci pole s hodnotou indexu můžete použít k získání přístupu k jednotlivým znakům pro čtení, jak je uvedeno v následujícím příkladu.

string s5 = "Printing backwards";

for (int i = 0; i < s5.Length; i++)
{
    System.Console.Write(s5[s5.Length - i - 1]);
}
// Output: "sdrawkcab gnitnirP"

Pokud metody String neposkytují potřebnou funkčnost pro úpravu jednotlivých znaků v řetězci, můžete pomocí objektu StringBuilder upravit jednotlivé znaky přímo v paměti a poté vytvořit nový řetězec pro uložení výsledků pomocí metod StringBuilder. V následujícím příkladu předpokládejme, že musíte upravit původní řetězec určitým způsobem a uložit výsledky pro budoucí použití:

string question = "hOW DOES mICROSOFT wORD DEAL WITH THE cAPS lOCK KEY?";
System.Text.StringBuilder sb = new System.Text.StringBuilder(question);

for (int j = 0; j < sb.Length; j++)
{
    if (System.Char.IsLower(sb[j]) == true)
        sb[j] = System.Char.ToUpper(sb[j]);
    else if (System.Char.IsUpper(sb[j]) == true)
        sb[j] = System.Char.ToLower(sb[j]);
}
// Store the new string.
string corrected = sb.ToString();
System.Console.WriteLine(corrected);
// Output: How does Microsoft Word deal with the Caps Lock key?

Řetězce s hodnotou Null a prázdné řetězce

Prázdný řetězec je instance objektu System.String, který neobsahuje žádné znaky. Prázdné řetězce se často používají v různých programovacích scénářích k reprezentaci prázdného textového pole. Metody můžete volat na prázdných řetězcích, protože jsou to platné objekty System.String. Prázdné řetězce se inicializují následujícím způsobem:

string s = String.Empty;

Naproti tomu řetězec null neodkazuje na instanci objektu System.String a jakýkoli pokus o volání metody v řetězci null způsobí NullReferenceException. V operacích zřetězení a porovnávání s jinými řetězci však můžete použít řetězce null. Následující příklady ilustrují některé případy, kdy odkaz na řetězec null způsobí vyvolání výjimky a kdy ne.

string str = "hello";
string? nullStr = null;
string emptyStr = String.Empty;

string tempStr = str + nullStr;
// Output of the following line: hello
Console.WriteLine(tempStr);

bool b = (emptyStr == nullStr);
// Output of the following line: False
Console.WriteLine(b);

// The following line creates a new empty string.
string newStr = emptyStr + nullStr;

// Null strings and empty strings behave differently. The following
// two lines display 0.
Console.WriteLine(emptyStr.Length);
Console.WriteLine(newStr.Length);
// The following line raises a NullReferenceException.
//Console.WriteLine(nullStr.Length);

// The null character can be displayed and counted, like other chars.
string s1 = "\x0" + "abc";
string s2 = "abc" + "\x0";
// Output of the following line: * abc*
Console.WriteLine("*" + s1 + "*");
// Output of the following line: *abc *
Console.WriteLine("*" + s2 + "*");
// Output of the following line: 4
Console.WriteLine(s2.Length);

Použití StringBuilderu k rychlému vytváření řetězců

Řetězcové operace v .NET jsou vysoce optimalizované a ve většině případů nemají významný vliv na výkon. V některých scénářích, jako jsou těsné smyčky, které se opakují mnohokrát stovky nebo tisícekrát, mohou operace s řetězci ovlivnit výkon. Pokud váš program provádí mnoho manipulací s řetězci, třída StringBuilder vytvoří buffer řetězce, který nabízí lepší výkon. Řetězec StringBuilder také umožňuje znovu přiřadit jednotlivé znaky, něco, co předdefinovaný datový typ řetězce nepodporuje. Tento kód například změní obsah řetězce bez vytvoření nového řetězce:

System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
//Outputs Cat: the ideal pet

V tomto příkladu se objekt StringBuilder používá k vytvoření řetězce ze sady číselných typů:

var sb = new StringBuilder();

// Create a string composed of numbers 0 - 9
for (int i = 0; i < 10; i++)
{
    sb.Append(i.ToString());
}
Console.WriteLine(sb);  // displays 0123456789

// Copy one character of the string (not possible with a System.String)
sb[0] = sb[9];

Console.WriteLine(sb);  // displays 9123456789

Řetězce, rozšiřující metody a LINQ

Protože typ String implementuje IEnumerable<T>, můžete použít rozšiřující metody definované ve třídě Enumerable na řetězcích. Aby nedocházelo k nepřehledným vizuálním prvkům, jsou tyto metody vyloučeny z Technologie IntelliSense pro typ String, ale jsou však k dispozici. U řetězců můžete také použít výrazy dotazu LINQ. Další informace naleznete v tématu LINQ a řetězce.