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

Řetězec je objekt typu String , jehož hodnota je text. Interně se text ukládá jako sekvenční kolekce Char objektů jen pro čtení. Na konci řetězce jazyka C# neexistuje žádný znak ukončující hodnotu null; řetězec jazyka C# proto může obsahovat libovolný počet vložených znaků null ('\0'). Length Vlastnost ř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# string je klíčové slovo aliasem pro String. Proto a string jsou ekvivalentní, String bez ohledu na to, že se doporučuje použít zadaný aliasstring, protože funguje i bez using System;. Třída String poskytuje mnoho metod pro bezpečné vytváření, manipulaci a porovnávání řetězců. Jazyk C# navíc přetíží některé operátory, aby zjednodušily běžné operace řetězců. Další informace o klíčovém slově najdete v řetězci. 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);

Nový operátor nepoužíváte k vytvoření řetězcového objektu s výjimkou inicializace řetězce s polem znaků.

Inicializace řetězce s Empty konstantní hodnotou pro vytvoření nového String objektu, jehož řetězec má nulovou délku. Řetězcový literál reprezentace řetězce nulové délky je "". Inicializací řetězců s Empty hodnotou namísto hodnoty null můžete snížit pravděpodobnost výskytu NullReferenceException . Statickou IsNullOrEmpty(String) metodu použijte k ověření hodnoty řetězce před pokusem o přístup k řetězci.

Neměnnost řetězců

Objekty řetězců jsou neměnné: po vytvoření je nelze změnit. String Všechny metody a operátory jazyka C#, které se zdá upravit řetězec, skutečně vrací výsledky v novém řetězcovém objektu. V následujícím příkladu se při zřetězení obsahu s1 a s2 zřetězení tvoří jeden řetězec, tyto dva původní řetězce jsou nezměněné. Operátor += vytvoří nový řetězec, který obsahuje kombinovaný obsah. Tento nový objekt je přiřazen k proměnné s1a původní objekt, ke kterému byl přiřazen s1 , je uvolněn pro uvolňování paměti, protože žádná jiná proměnná neobsahuje odkaz na ni.

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 řetězec "úprava" je ve skutečnosti nové vytvoření řetězce, musíte při vytváření odkazů na řetězce použít upozornění. Pokud vytvoříte odkaz na řetězec a pak původní řetězec "upravíte", odkaz bude dál 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 hledání a nahrazení operací v původním řetězci, najdete v tématu Jak upravit obsah řetězce.

Řetězcové literály s citací

Řetězcové literály uvozovek začínají a končí jedním znakem uvozovek (") na stejném řádku. Řetězcové literály s uvozovými řetězci jsou nejvhodnější pro řetězce, které se vejdou na jeden řádek, a neobsahují žádné řídicí 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 vhodnější pro víceřádkové řetězce, řetězce, které obsahují znaky zpětného lomítka nebo vložené dvojité uvozovky. Doslovné řetězce zachovávají nové znaky řádku jako součást textu řetězce. Pomocí dvojitých uvozovek můžete vložit uvozovky do doslovné řetězce. Následující příklad ukazuje některé běžné použití pro doslovné řetězce:

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 pomocí nezpracovaných řetězcových literálů snadněji vytvářet řetězce, které jsou víceřádkové, nebo použít všechny znaky vyžadující řídicí sekvence. Nezpracované řetězcové literály odstraňují potřebu někdy používat řídicí sekvence. Řetězec, včetně formátování prázdných znaků, můžete napsat tak, jak se má zobrazit ve výstupu. Nezpracovaný řetězcový literál:

  • Začíná a končí posloupností alespoň tří dvou uvozovek ("""). Chcete-li podporovat řetězcové literály obsahující tři (nebo více) opakovaných uvozovek, můžete spustit a ukončit posloupnost více než tři po sobě jdoucí znaky.
  • Jednořádkové nezpracované řetězcové literály vyžadují levou a pravou uvozovku na stejném řádku.
  • Nezpracované řetězcové literály s více řádky vyžadují otevření i zavření uvozovek na vlastním řádku.
  • V nezpracovaných řetězcových literálech s více řádky se odeberou všechny prázdné znaky vlevo od uvozovek.

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í levou a pravou uvozovku na vlastním řádku. Třetí příklad je neplatný, protože text je odsud odsazení z uzavírací sekvence uvozovek.

Při generování textu obsahujícího znaky, které vyžadují řídicí sekvence při použití řetězcových literálů nebo doslovných řetězcových literálů, byste měli zvážit nezpracované řetězcové literály. Nezpracované řetězcové literály budou pro vás a ostatní snadněji čitelné, protože bude blíže vypadat jako výstupní text. 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"
  ]
}
""";

Porovnejte tento text s ekvivalentním textem v naší ukázce serializace JSON, který tuto novou funkci nepoužívá.

Řídicí sekvence řetězců

Řídicí sekvence Název znaku Kódování Unicode
\' Jednoduchá uvozovka 0x0027
\" Dvojitá uvozovka 0x0022
\\ Zpětné lomítko 0x005C
\0 Null 0x0000
\a Výstrahy 0x0007
\b Backspace 0x0008
\f Informační kanál formuláře 0x000C
\n Nový řádek 0x000A
\r Návrat na začátek řádku 0x000D
\t Horizontální tabulátor 0x0009
\v Vertikální tabulátor 0x000B
\u Řídicí sekvence Unicode (UTF-16) \uHHHH (rozsah: 0000 - FFFF; příklad: \u00E7 = "ç")
\U Řídicí sekvence Unicode (UTF-32) \U00HHHHHH (rozsah: 000000 - 10FFFF; příklad: \U0001F47D = "👽")
\x Řídicí sekvence Unicode podobná "\u" s výjimkou délky proměnné \xH[H][H][H] (rozsah: 0 – FFFF; příklad: \x00E7 nebo \x0E7\xE7 = "ç")

Upozornění

Pokud použijete \x řídicí sekvenci a zadáte méně než 4 šestnáctkové číslice, jsou-li znaky, které bezprostředně následují řídicí sekvence, 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", bude řídicí sekvence interpretována jako " \xA1A ਚ", což je bod kódu U+0A1A. Vtakovýchch kódech se v takových případech zabrání určení všech 4 šestnáctkových číslic (např \x00A1 . )

Poznámka

V době kompilace se doslovné ř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 doslovný řetězec, zobrazí se řídicí znaky přidané kompilátorem, nikoli doslovná verze ze zdrojového kódu. Například doslovný řetězec @"C:\files.txt" se zobrazí v okně kukátka 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ů uvnitř závorek v řetězci. Vše uvnitř závorek ({...}) se přeloží na hodnotu a výstup jako formátovaný řetězec za běhu. Existují dvě metody pro vytváření formátových řetězců: interpolace řetězců a složené formátování.

Interpolace řetězců

V jazyce C# 6.0 a novější jsou interpolované řetězce identifikovány speciálním $ znakem a obsahují interpolované výrazy do závorek. Pokud s interpolací řetězců začínáte, podívejte se na interaktivní kurz Interpolace řetězců – C# s rychlým přehledem.

Pomocí interpolace řetězců můžete zlepšit čitelnost a udržovatelnost kódu. Interpolace řetězců dosahuje stejných výsledků jako String.Format metoda, ale zlepšuje snadné použití a vloženou srozumitelnost.

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.

Počínaje jazykem C# 10 můžete pomocí interpolace řetězců inicializovat konstantní řetězec, když všechny výrazy použité 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 má výstupní řetězec obsahovat { znak nebo } znak, můžete použít další $ znaky k určení počtu { počátečních a } koncových znaků interpolace. Ve výstupu je zahrnuta libovolná posloupnost menšího { počtu znaků nebo } znaků. Následující příklad ukazuje, jak tuto funkci použít k zobrazení vzdálenosti bodu od původu a umístění bodu uvnitř 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.

Složené formátování

Používá String.Format zástupné symboly ve složených závorkách k vytvoření řetězce formátu. Výsledkem tohoto příkladu je podobný výstup jako metoda interpolace řetězců použitá výše.

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 najdete v tématu Typy formátování v .NET.

Podřetězců

Podřetězce je libovolná posloupnost znaků obsažených v řetězci. Substring Pomocí metody vytvořte nový řetězec z části původního řetězce. Pomocí metody můžete vyhledat jeden nebo více výskytů podřetěžky IndexOf . Replace Pomocí metody nahraďte všechny výskyty zadaného podřetězce novým řetězcem. Substring Podobně jako metoda Replace ve skutečnosti vrátí nový řetězec a nezmění původní řetězec. Další informace najdete v tématu Jak prohledávat ř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

Zápis pole s hodnotou indexu můžete použít k získání přístupu jen pro čtení k jednotlivým znakům, jako 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"

String Pokud metody neposkytují funkce, které musíte upravit jednotlivé znaky v řetězci, můžete pomocí StringBuilder objektu upravit jednotlivé znaky "na místě" a pak vytvořit nový řetězec pro uložení výsledků pomocí StringBuilder metod. V následujícím příkladu předpokládejme, že musíte upravit původní řetězec určitým způsobem a pak 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 null a prázdné řetězce

Prázdný řetězec je instance objektu System.String , který obsahuje nula znaků. 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 u prázdných řetězců, protože jsou platné System.String objekty. Prázdné řetězce jsou inicializovány 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 zřetězení a porovnávání operací s jinými řetězci ale můžete použít řetězce null. Následující příklady ilustrují některé případy, kdy odkaz na řetězec null dělá a nezpůsobí vyvolání výjimky:

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 pro rychlé vytváření řetězců

Operace řetězců 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 úzké smyčky, které provádějí mnoho stovek nebo tisíckrát, ale operace řetězců můžou ovlivnit výkon. Třída StringBuilder vytvoří vyrovnávací paměť řetězců, která nabízí lepší výkon, pokud program provádí mnoho manipulace s řetězci. Ř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 StringBuilder se objekt 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

Vzhledem k tomu, že String typ implementuje IEnumerable<T>, můžete použít rozšiřující metody definované ve Enumerable třídě u řetězců. Aby nedocházelo k nepotřebným vizuálním prvkům, jsou tyto metody pro tento typ vyloučeny z IntelliSense String , ale jsou však dostupné. U řetězců můžete také použít výrazy dotazu LINQ. Další informace najdete v tématu LINQ a Řetězce.