Strings

A C# string is a group of one or more characters declared using the string keyword, which is a C# language shortcut for the System.String class. Strings in C# are much easier to use, and much less prone to programming errors, than character arrays in C or C++.

A string literal is declared using quotation marks, as shown in the following example:

string greeting = "Hello, World!";

You can extract substrings, and concatenate strings, like this:

string s1 = "orange";
string s2 = "red";

s1 += s2;
System.Console.WriteLine(s1);  // outputs "orangered"

s1 = s1.Substring(2, 5);
System.Console.WriteLine(s1);  // outputs "anger"

String objects are immutable in that they cannot be changed once created. Methods that act on strings actually return new string objects. Therefore, for performance reasons, large amounts of concatenation or other involved string manipulation should be performed with the StringBuilder class, as demonstrated in the code examples below.

Working with Strings

Escape Characters

Escape characters such as "\n" (new line) and "\t" (tab) can be included in strings.

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

If you want to include a backward slash, it must be preceded with another backward slash. The following code:

string myfilepath = "\\\\My Documents\\";
System.Console.WriteLine(myfilepath);

displays the following string:

\\My Documents\

The @ Symbol

The @ symbol specifies that escape characters and line breaks should be ignored when the string is created. The following two strings are therefore identical:

string p1 = "\\\\My Documents\\My Files\\";
string p2 = @"\\My Documents\My Files\";

ToString()

The C# built-in data types all provide the ToString method, which converts a value to a string. This method can be used to convert numeric values into strings, like this:

int year = 1999;
string msg = "Eve was born in " + year.ToString();
System.Console.WriteLine(msg);  // outputs "Eve was born in 1999"

Accessing Individual Characters

Individual characters contained in a string can be accessed using methods such as Substring, Replace, Split and Trim.

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

It is also possible to copy the characters into a character array, like this:

string s4 = "Hello, World";
char[] arr = s4.ToCharArray(0, s4.Length);

foreach (char c in arr)
{
    System.Console.Write(c);  // outputs "Hello, World"
}

Individual characters from a string can be accessed with an index, like this:

string s5 = "Printing backwards";

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

Changing Case

To change the letters in a string to upper or lower case, use ToUpper() or ToLower(), like this:

string s6 = "Battle of Hastings, 1066";

System.Console.WriteLine(s6.ToUpper());
// outputs "BATTLE OF HASTINGS 1066"
System.Console.WriteLine(s6.ToLower());
// outputs "battle of hastings 1066"

Comparisons

The best way to compare two non-localized strings is to use the Equals method with the StringComparison.Ordinal and StringComparison.OrdinalIgnoreCase.

// Internal strings that will never be localized. 
string root = @"C:\users";
string root2 = @"C:\Users";

// Use the overload of the Equals method that specifies a StringComparison. 
// Ordinal is the fastest way to compare two strings. 
bool result = root.Equals(root2, StringComparison.Ordinal);

Console.WriteLine("Ordinal comparison: {0} and {1} are {2}", root, root2,
                    result ? "equal." : "not equal.");

// To ignore case means "user" equals "User". This is the same as using 
// String.ToUpperInvariant on each string and then performing an ordinal comparison.
result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine("Ordinal ignore case: {0} and {1} are {2}", root, root2,
                     result ? "equal." : "not equal.");

// A static method is also available. 
bool areEqual = String.Equals(root, root2, StringComparison.Ordinal);


// String interning. Are these really two distinct objects? 
string a = "The computer ate my source code.";
string b = "The computer ate my source code.";

// ReferenceEquals returns true if both objects 
// point to the same location in memory. 
if (String.ReferenceEquals(a, b))
    Console.WriteLine("a and b are interned.");
else
    Console.WriteLine("a and b are not interned.");

// Use String.Copy method to avoid interning. 
string c = String.Copy(a);

if (String.ReferenceEquals(a, c))
    Console.WriteLine("a and c are interned.");
else
    Console.WriteLine("a and c are not interned.");

The output from the previous example is the following:

Ordinal comparison: C:\users and C:\Users are not equal.

Ordinal ignore case: C:\users and C:\Users are equal.

a and b are interned.

a and c are not interned.

String objects also have a CompareTo() method that returns an integer value based on whether one string is less-than (<) or greater-than (>) another. When comparing strings, the Unicode value is used, and lower case has a smaller value than upper case.

// Enter different values for string1 and string2 to 
// experiement with behavior of CompareTo 
string string1 = "ABC";
string string2 = "abc";

int result2 = string1.CompareTo(string2);

if (result2 > 0)
{
    System.Console.WriteLine("{0} is greater than {1}", string1, string2);
}
else if (result2 == 0)
{
    System.Console.WriteLine("{0} is equal to {1}", string1, string2);
}
else if (result2 < 0)
{
    System.Console.WriteLine("{0} is less than {1}", string1, string2);
}
// Output: ABC is greater than abc

To search for a string inside another string, use IndexOf(). IndexOf() returns -1 if the search string is not found; otherwise, it returns the zero-based index of the first location at which it occurs.

string s9 = "Battle of Hastings, 1066";
System.Console.WriteLine(s9.IndexOf("Hastings"));
// Output: 10
System.Console.WriteLine(s9.IndexOf("1967"));
// Output: -1

Splitting a String into Substrings

Splitting a string into substrings, such as, splitting a sentence into individual words, is a common programming task. The Split() method takes a char array of delimiters, for example, a space character, and returns an array of substrings. You can access this array with foreach, like this:

char[] delimit = new char[] { ' ' };
string s10 = "The cat sat on the mat.";
foreach (string substr in s10.Split(delimit))
{
    System.Console.WriteLine(substr);
}

This code outputs each word on a separate line, like this:

The

cat

sat

on

the

mat.

Using StringBuilder

The StringBuilder class creates a string buffer that offers better performance if your program performs a lot of string manipulation. The StringBuilder class also allows you to reassign individual characters, something the built-in string data type does not support.

In this example, a StringBuilder object is created, and its contents are added one by one using the Append method.

class TestStringBuilder
{
    static void Main()
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();

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

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

        System.Console.WriteLine(sb);  // displays 9123456789
    }
}

See Also

Tasks

How to: Generate Multiline String Literals

How to: Search for a String in an Array of Strings

How to: Search Within a String

Concepts

C# Language Primer

Built-in Data Types

Reference

string (C# Reference)