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.
- First word. Start at index 0 and take 6 characters to get
Coding:Substring(0, 6). - 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), givingfeels. - Last word.
greatstarts 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
substringorslice. C# method names are case-sensitive and PascalCase: it isSubstring, 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 fromstartto 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.