Start learning free

LESSON 56 OF 347 · STRINGS I

String Slicing in C#: Substring Explained

Lesson Read the full explanation

Not only we can select a single character from a string, but we can also select a sequence of consecutive characters (e.g. substring) from a string.

To achieve this, we use the substring() method like this:

string.Substring(startIndex, endIndex);

This is called slicing a string. It returns the substring from startIndex to endIndex.

Here is an example:

string language = "JavaScript";
string substring = language.Substring(2, 6);

Console.WriteLine(substring); // Output: "vaSc"
Console.WriteLine(language); // Output: "JavaScript"

The startIndex is a zero-based index at which we start extraction and the endIndex is also zero-based index before which we end the extraction.

The substring will not include the character at endIndex. You can see in our example that the character at index 2 (v) was included while the character at index 6 (r) was excluded.

Also notice that language preserved its value. The slicing does not affect the original string. It just creates a brand new one representing the sliced substring.


If you omit the endIndex, the slice() extracts to the end of the string:

string language = "JavaScript";
string substring = language.Substring(4);

Console.WriteLine(substring); // Output: "Script"

Assignment
Follow the Coding Tutorial and let's slice some strings!


Hint
Look at the examples above if you get stuck.


STEP 1 OF 3
    Ctrl + Enter to check

    C# · STRINGS I

    String Slicing in C#, explained

    What slicing is

    Slicing means taking a run of consecutive characters out of a string. The everyday tool in C# is the Substring method. It never changes the original string. It builds and returns a new one, which you usually store in a variable.

    To use it well, you need to know how the characters are numbered. Indexes start at 0, so in "JavaScript" the letters sit at these positions:

    J  a  v  a  S  c  r  i  p  t
    0  1  2  3  4  5  6  7  8  9
    

    Substring takes a start and a length

    This is the detail that trips people up. Substring(startIndex, length) takes the index where extraction starts and the number of characters to take. The second argument is not an end index. Languages such as Java and JavaScript use an end index, so code ported from them often gets this wrong.

    string language = "JavaScript";
    
    Console.WriteLine(language.Substring(2, 4));  // vaSc
    Console.WriteLine(language.Substring(2, 6));  // vaScri
    Console.WriteLine(language);                  // JavaScript
    

    In "JavaScript", index 2 is v. Taking 4 characters from there gives vaSc, and taking 6 gives vaScri. The original variable still holds JavaScript afterwards, because strings are immutable.

    If you know an end index instead, the length is end - start. To get the characters at indexes 2 up to but not including 6, ask for 6 - 2 = 4 characters.

    Leaving out the length

    With only a start index, Substring returns everything from that index to the end of the string:

    string language = "JavaScript";
    
    Console.WriteLine(language.Substring(4));   // Script
    Console.WriteLine(language.Substring(10));  // prints an empty line
    

    A start index equal to the string's length is allowed and gives an empty string. A start index beyond that is not.

    Ranges as an alternative

    Modern C# also lets you slice a string with the range operator. The end of a range is exclusive, and ^ counts from the end:

    string language = "JavaScript";
    
    Console.WriteLine(language[2..6]);  // vaSc
    Console.WriteLine(language[4..]);   // Script
    Console.WriteLine(language[^6..]);  // Script
    

    This lesson uses Substring, which works in every version of C#.

    When Substring throws

    Substring throws an ArgumentOutOfRangeException when the request does not fit inside the string. That happens when:

    • the start index is negative or larger than the string's length;
    • the length is negative;
    • the start index plus the length goes past the end of the string.

    For example, "JavaScript".Substring(8, 5) asks for five characters when only two remain, so it throws. Unlike some other languages, C# does not quietly shorten the result.

    The exercise, step by step

    The lesson starts with message set to "Coding feels great". Its characters are numbered like this: Coding is indexes 0 to 5, the space is 6, feels is 7 to 11, the next space is 12, and great is 13 to 17.

    1. First word. Start at index 0 and take 6 characters to get Coding: Substring(0, 6).
    2. Middle word. The 8th character is at index 7, because counting starts at 0. The 8th through 12th characters are 5 characters, so the call is Substring(7, 5), giving feels.
    3. Last word. great starts at index 13 and runs to the end, so the start index alone is enough: Substring(13).
    string message = "Coding feels great";
    
    string firstWord = message.Substring(0, 6);
    string middleWord = message.Substring(7, 5);
    string lastWord = message.Substring(13);
    

    The three variables then hold Coding, feels and great.

    Slicing around a separator

    Slicing becomes more useful when you let the string tell you where to cut. IndexOf returns the index of a character or text, and you can feed that into Substring:

    string name = "Andrei Chiriac";
    int space = name.IndexOf(' ');
    
    string first = name.Substring(0, space);   // Andrei
    string last = name.Substring(space + 1);   // Chiriac
    

    The length for the first part is exactly space, because the characters before the space are at indexes 0 up to space - 1. The second part starts one position after the space, hence space + 1.

    Common mistakes

    • Treating the second argument as an end index. Substring(2, 6) does not stop before index 6. It takes 6 characters and ends before index 8.
    • Counting from 1. The 8th character is at index 7. Subtract one from any "nth" in plain English.
    • Forgetting to keep the result. message.Substring(0, 6); on its own line does nothing useful, because the new string is thrown away.
    • Calling substring or slice. C# method names are case-sensitive and PascalCase: it is Substring, with a capital S.

    Key takeaways

    • Substring(start, length) takes a start index and a character count, not an end index.
    • Substring(start) takes everything from start to the end.
    • The original string is never modified; you get a new string.
    • A request that does not fit inside the string throws ArgumentOutOfRangeException.
    • To convert an end index into a length, subtract: end - start.
    Keep going with C#About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free