Dela via


Strängar och strängliteraler

En sträng är ett objekt av typen String vars värde är text. Internt lagras texten som en sekventiell skrivskyddad samling av objekt Char. Egenskapen Length för en sträng representerar antalet Char objekt som den innehåller, inte antalet Unicode-tecken. Använd objektet för att komma åt enskilda Unicode-kodpunkter i en sträng StringInfo .

string vs. System.String

I C# är nyckelordet string ett alias för String; därför String och string är likvärdigt. Använd det angivna aliaset string eftersom det fungerar även utan using System;. Klassen String innehåller många metoder för att på ett säkert sätt skapa, manipulera och jämföra strängar. Dessutom överbelastar C#-språket vissa operatorer för att förenkla vanliga strängåtgärder. Mer information om nyckelordet finns i strängen. Mer information om typen och dess metoder finns i String.

Deklarera och initiera strängar

Du kan deklarera och initiera strängar på olika sätt, som du ser i följande exempel:

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

Du använder inte den nya operatorn för att skapa ett strängobjekt förutom när du initierar strängen med en matris med tecken.

Initiera en sträng med konstantvärdet Empty för att skapa ett nytt String objekt vars sträng är av noll längd. Strängliteralrepresentationen av en sträng med noll längd är "". Genom att initiera strängar med Empty värdet i stället för null kan du minska risken för att ett NullReferenceException inträffar. Använd den statiska IsNullOrEmpty(String) metoden för att verifiera värdet för en sträng innan du försöker komma åt den.

Oföränderlighet för strängar

Strängobjekt är oföränderliga: de kan inte ändras när de har skapats. String Alla metoder och C#-operatorer som verkar ändra en sträng returnerar faktiskt resultatet i ett nytt strängobjekt. I följande exempel, när innehållet i s1 och s2 sammanfogas för att bilda en enda sträng, är de två ursprungliga strängarna oförändrade. Operatorn += skapar en ny sträng som innehåller det kombinerade innehållet. Det nya objektet tilldelas variabeln s1, och det ursprungliga objektet som tilldelades s1 släpps för skräpinsamling eftersom ingen annan variabel innehåller en referens till det.

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.

Eftersom en "ändring" av en sträng faktiskt innebär att en ny sträng skapas, måste du vara försiktig när du skapar referenser till strängar. Om du skapar en referens till en sträng och sedan "ändrar" den ursprungliga strängen fortsätter referensen att peka på det ursprungliga objektet i stället för det nya objekt som skapades när strängen ändrades. Följande kod illustrerar det här beteendet:

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

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

Mer information om hur du skapar nya strängar som baseras på ändringar som sök- och ersättningsåtgärder på den ursprungliga strängen finns i Ändra stränginnehåll.

Citerade strängliteraler

Citerade strängliteraler börjar och slutar med ett enda dubbelt citattecken (") på samma rad. Citerade strängliteraler passar bäst för strängar som passar på en enda rad och som inte innehåller några escape-sekvenser. En citerad strängliteral måste bädda in escape-tecken, som du ser i följande exempel:

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

Ordagranna strängliteraler

Ordagranna strängliteraler är mer praktiska för strängar med flera rader, strängar som innehåller bakåtsnedstreck eller inbäddade dubbla citattecken. Ordagranna strängar bevarar nya radtecken som en del av strängtexten. Använd dubbla citattecken för att bädda in ett citattecken i en ordagrann sträng. I följande exempel visas några vanliga användningsområden för ordagranna strängar:

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."

Råa strängliteraler

Från och med C# 11 kan du använda råa strängliteraler för att enklare skapa strängar som är flerradssträngar eller använda tecken som kräver escape-sekvenser. Råa strängliteraler tar bort behovet av att någonsin använda escape-sekvenser. Du kan skriva strängen, inklusive blankstegsformatering, hur du vill att den ska visas i utdata. En rå strängliteral:

  • Startar och slutar med en sekvens med minst tre dubbla citattecken ("""). Du kan använda fler än tre tecken i följd för att starta och avsluta sekvensen för att stödja strängliteraler som innehåller tre (eller fler) upprepade citattecken.
  • Enradsliteraler för råsträng kräver inledande och avslutande citattecken på samma rad.
  • Strängliteraler med flera rader kräver att både de inledande och avslutande citattecknen placeras på varsin egen rad.
  • I strängliteraler med flera rader tas alla blanksteg till vänster om de avslutande citattecknen bort från alla rader i den råa strängliteralen.
  • I strängliteraler med flera rader ignoreras blanksteg som följer öppningscitatet på samma rad.
  • I strängliteraler med flera rader ingår endast rader med blanksteg som följer det inledande citattecknet i strängliteralen.

Följande exempel visar dessa regler:

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: """
    """";

Följande exempel visar de kompilatorfel som rapporterats baserat på dessa regler:

// 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.
    """;

De första två exemplen är ogiltiga eftersom råsträngliteraler med flera rader kräver att de inledande och avslutande citattecknen står på en egen rad. Det tredje exemplet är ogiltigt eftersom texten har flyttats ut från den avslutande citattecknet.

Du bör överväga råa strängliteraler när du genererar text som innehåller tecken som kräver escape-sekvenser när du använder citerade strängliteraler eller ordagranna strängliteraler. Råsträngliteraler är enklare för dig och andra att läsa eftersom de liknar utdatatexten närmare. Tänk till exempel på följande kod som innehåller en sträng med formaterad 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"
  ]
}
""";

Escape-sekvenser för strängar

Escape-sekvens Karaktärsnamn Unicode-kodning
\' Enkelt citat 0x0027
\" Dubbelt citat 0x0022
\\ Omvänt snedstreck 0x005C
\0 Noll 0x0000
\a Avisering 0x0007
\b Backstegstangent 0x0008
\e Flykt 0x001B
\f Formulärfeed 0x000C
\n Ny rad 0x000A
\r Vagnretur 0x000D
\t Horisontell tabb 0x0009
\v Vertikal tabb 0x000B
\u Unicode-escape-sekvens (UTF-16) \uHHHH (intervall: 0000 – FFFF; exempel: \u00E7 = "ç")
\U Unicode escape-sekvens (UTF-32) \U00HHHHHH (intervall: 000000 - 10FFFF; exempel: \U0001F47D = "👽"))
\x Unicode escape-sekvens som liknar "\u" förutom med variabel längd \xH[H][H][H] (intervall: 0 – FFFF; exempel: \x00E7 eller \x0E7\xE7 = "ç")

Varning

När du använder escape-sekvensen \x och anger mindre än 4 hexsiffror, om tecknen som omedelbart följer escape-sekvensen är giltiga hexsiffror (dvs. 0-9, A-F och a-f), tolkas de som en del av escape-sekvensen. Till exempel \xA1 genererar "¡", som är kodpunkten U+00A1. Men om nästa tecken är "A" eller "a" tolkas escape-sekvensen i stället som att den är \xA1A och producerar "ਚ", vilket är kodpunkten U+0A1A. Om du i sådana fall anger alla fyra hexsiffror (till exempel \x00A1) förhindras eventuell feltolkning.

Anmärkning

Vid kompilering konverteras bokstavliga och råa strängar till vanliga strängar med alla motsvarande escape-sekvenser. Om du visar en ordagrann eller rå sträng i visningsfönstret för felsökningsprogrammet ser du därför escape-tecknen som har lagts till av kompilatorn, inte den ordagranta eller råa versionen från källkoden. Till exempel visas den ordagranna strängen @"C:\files.txt" i klockfönstret som "C:\\files.txt".

Formatera strängar

En formatsträng är en sträng vars innehåll bestäms dynamiskt vid körningstid. Formatsträngar skapas genom inbäddning av interpolerade uttryck eller platshållare inuti klammerparenteser i en sträng. Allt inom klammerparenteserna ({...}) matchas till ett värde och utdata som en formaterad sträng vid körning. Det finns två metoder för att skapa formatsträngar: stränginterpolation och sammansatt formatering.

Stränginterpolation

Du deklarerar interpolerade strängar med $ specialtecknet. En interpolerad sträng innehåller interpolerade uttryck i klammerparenteser. Om du inte har använt stränginterpolation tidigare kan du läsa självstudien Stränginterpolation – C# för flera exempel.

Använd stränginterpolation för att förbättra kodens läsbarhet och underhåll. Stränginterpolation uppnår samma resultat som String.Format metoden, men är lättare att använda och förbättrar den infogade klarheten.

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.

Du kan använda stränginterpolation för att initiera en konstant sträng när alla uttryck som används för platshållare också är konstanta strängar.

Från och med C# 11 kan du kombinera råa strängliteraler med stränginterpolationer. Du startar och avslutar formatsträngen med tre eller fler på varandra följande dubbla citattecken. Om din utdatasträng ska innehålla tecknen { eller }, kan du använda extra tecken $ för att ange hur många {- och }-tecken som ska starta och avsluta en interpolation. Alla sekvenser med färre { tecken eller } tecken ingår i utdata. I följande exempel visas hur du kan använda funktionen för att visa avståndet för en punkt från ursprunget och placera punkten inuti klammerparenteser:

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.

Ordagrann stränginterpolation

C# tillåter också ordagrann stränginterpolation, till exempel över flera rader, med hjälp av syntaxen $@ eller @$ .

Om du vill tolka escape-sekvenser bokstavligen använder du en verbatimsträng. En interpolerad ordagrann sträng börjar med $-tecknet följt av @-tecknet. Du kan använda $ och @ token i valfri ordning: både $@"..." och @$"..." är giltiga interpolerade ordagranna strängar.

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.

Sammansatt formatering

String.Format använder platshållare i klammerparenteser för att skapa en formatsträng. Det här exemplet resulterar i liknande utdata som stränginterpoleringsmetoden som användes i föregående exempel.

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.

Mer information finns i Sammansatt formatering i .NET.

Delsträngar

En delsträng är en sekvens med tecken som finns i en sträng. Substring Använd metoden för att skapa en ny sträng från en del av den ursprungliga strängen. Du kan söka efter en eller flera förekomster av en delsträng med hjälp IndexOf av metoden . Replace Använd metoden för att ersätta alla förekomster av en angiven delsträng med en ny sträng. Substring Precis som metoden Replace returnerar faktiskt en ny sträng och ändrar inte den ursprungliga strängen. Mer information finns i Så här söker du efter strängar och Ändrar stränginnehåll.

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

Åtkomst till enskilda tecken

Du kan använda matrisnotation med ett indexvärde för att få skrivskyddad åtkomst till enskilda tecken, som i följande exempel:

string s5 = "Printing backwards";

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

Om String metoderna inte tillhandahåller den funktionalitet som krävs för att ändra enskilda tecken i en sträng, kan du använda ett StringBuilder objekt för att ändra de enskilda tecknen "på plats" och sedan skapa en ny sträng för att lagra resultaten med hjälp av StringBuilder metoderna. Anta i följande exempel att du måste ändra den ursprungliga strängen på ett visst sätt och sedan lagra resultatet för framtida användning:

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?

Null-strängar och tomma strängar

En tom sträng är en instans av ett System.String objekt som innehåller noll tecken. Tomma strängar används ofta i olika programmeringsscenarier för att representera ett tomt textfält. Du kan anropa metoder på tomma strängar eftersom de är giltiga System.String objekt. Tomma strängar initieras på följande sätt:

string s = String.Empty;

En null-sträng refererar däremot inte till en instans av ett System.String objekt och varje försök att anropa en metod för en null-sträng orsakar en NullReferenceException. Du kan dock använda null-strängar i sammanfognings- och jämförelseåtgärder med andra strängar. Följande exempel illustrerar några fall där en referens till en null-sträng gör och inte orsakar ett undantagsfel som genereras:

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

Använda StringBuilder för snabb skapande av strängar

Strängåtgärder i .NET är mycket optimerade och påverkar i de flesta fall inte prestanda avsevärt. Men i vissa scenarier, till exempel snäva loopar som körs många hundratals eller tusentals gånger, kan strängåtgärder påverka prestanda. Klassen StringBuilder skapar en strängbuffert som ger bättre prestanda om programmet utför många strängmanipuleringar. Med strängen StringBuilder kan du också omtilldela enskilda tecken, något som den inbyggda strängdatatypen inte stöder. Den här koden ändrar till exempel innehållet i en sträng utan att skapa en ny sträng:

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

I det här exemplet används ett StringBuilder objekt för att skapa en sträng från en uppsättning numeriska typer:

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

Strängar, tilläggsmetoder och LINQ

String Eftersom typen implementerar IEnumerable<T> kan du använda tilläggsmetoderna som definierats i Enumerable klassen på strängar. För att undvika visuell oreda undantas dessa metoder från IntelliSense för String typen, men de är ändå tillgängliga. Du kan också använda LINQ-frågeuttryck på strängar. Mer information finns i LINQ och Strängar.