C# Substring Examples

Use the Substring method with start and length ints. Substring gets parts of strings.

Substring. From above the eagle views the land. It perceives great detail. But it does not see all—what is visible is just a slice (a fragment) of what exists below.

Substring details. In this method we extract a fragment of an existing string. A start and length (both ints) describe this view. Like an eagle's view, Substring() considers only a part.

Example, first part. We extract the first part of a string into a new string. We can use the Substring method with 2 parameters—the first is 0 and the second is the desired length.

Argument 1: The starting index of the substring. Please remember strings are indexed with the first character 0.

Argument 2: The length of the substring part. This is not the final index, but the count of characters in the substring we want.

String Length
C# program that uses Substring using System; class Program { static void Main() { string input = "OneTwoThree"; // Get first three characters. string sub = input.Substring(0, 3); Console.WriteLine("Substring: {0}", sub); } } Output Substring: One

Methods. These are 2 Substring overloads. The first integer argument is always the start index. The second, optional argument is the desired length—not the end index.
Substring parameters Substring(0, 3) Returns substring of first 3 chars. Substring(3, 3) Returns substring of second 3 chars. Substring(6) Returns substring of all chars after first 6.

One parameter. This Substring overload receives just the start index int. The second parameter is considered the largest possible, meaning the substring ends at the last char.

Here: The program describes logic that takes all the characters in the input string excluding the first 3.

Result: We extract the last several characters from the string. The length is reduced by 3.

C# program that calls Substring, one argument using System; class Program { static void Main() { string input = "OneTwoThree"; // Indexes: // 0:'O' // 1:'n' // 2:'e' // 3:'T' // 4:'w' ... string sub = input.Substring(3); Console.WriteLine("Substring: {0}", sub); } } Output Substring: TwoThree

Middle chars. Here we take several characters in the middle of a string and place them into a new string. To take a middle substring, pass 2 arguments to Substring.

Note: We will want each argument to be a non-zero value to avoid the edge characters. Be careful to validate arguments.

Parameters: In this example, the two parameters say, "I want the substring at index 3 with a length of three."

C# program that uses Substring, two arguments using System; class Program { static void Main() { string input = "OneTwoThree"; string sub = input.Substring(3, 3); Console.WriteLine("Substring: {0}", sub); } } Output Substring: Two

Avoid chars. Here we eliminate the last few chars in a string. This example eliminates the last five characters from the input string. It returns a new string without them.

Info: This method reduces the length of a string. It will cause an error if the string is too short—a check would be needed.

Remove: The Remove method can be used to remove parts of strings too. It just internally forwards to Substring with the correct arguments.

C# program that uses Substring, ending characters using System; class Program { static void Main() { string input = "OneTwoThree"; string sub = input.Substring(0, input.Length - 5); Console.WriteLine("Substring: {0}", sub); } } Output Substring: OneTwo

IndexOf with Substring. The IndexOf method is made to be used with Substring (and other String methods). Here we want to parse a string by finding a separator.

Part 1: We call IndexOf to locate the position of the separator in the string. If found, the returned value is never -1.


Part 2: If the separator is found, we call Substring to get the following part. We add the separator's length to the start index.

C# program that uses IndexOf with Substring using System; class Program { static void Main() { string value = "Unit: 300 V"; string separator = ": "; // Part 1: get index of separator. int separatorIndex = value.IndexOf(separator); // Part 2: if separator exists, get substring. if (separatorIndex >= 0) { string result = value.Substring(separatorIndex + separator.Length); Console.WriteLine("RESULT: {0}", result); } } } Output RESULT: 300 V

Exceptions. Substring() must be passed arguments within the range of the string. Exceptions can help us fix problems faster. This example triggers the ArgumentOutOfRangeException.

Part A: Here we try to get a substring with a negative starting index—this makes no sense, and causes an error.

Part B: We cannot take a Substring with a length past the end of the source string. This causes an ArgumentOutOfRangeException.

C# program that shows exceptions using System; class Program { static void Main() { string input = "OneTwoThree"; // Part A: try negative start index. try { string sub = input.Substring(-1); } catch (Exception ex) { Console.WriteLine(ex); } // Part B: try excessive length. try { string sub = input.Substring(0, 100); } catch (Exception ex) { Console.WriteLine(ex); } } } Output System.ArgumentOutOfRangeException System.String.InternalSubStringWithChecks System.ArgumentOutOfRangeException System.String.InternalSubStringWithChecks

Null substring. If a string may be null, we need to test it against null before using Substring on it. We cannot take a Substring of a null string.

Info: We can use string.IsNullOrEmpty to prevent a NullReferenceException. This also checks for an empty string.

IsNullOrEmpty, IsNullOrWhiteSpace
C# program that causes NullReferenceException using System; class Program { static void Main() { string value = null; // This is safe. if (!string.IsNullOrEmpty(value)) { Console.WriteLine(value.Substring(1)); } // This will cause an exception. Console.WriteLine(value.Substring(1)); } } Output Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.

One character. It is possible to take a one-character substring. But if we simply use the string indexer to get a character, we will have better performance.

Note: Substring creates an object on the heap. The string indexer just returns a char, which is an integer-like value—this is faster.

C# program that uses char, Substring using System; class Program { static void Main() { string value = "cat"; // ... In many programs, we can use a char instead of Substring. Console.WriteLine(value[0]); Console.WriteLine(value.Substring(0, 1)); } } Output c c

Avoid substring. With logic, we can avoid invoking Substring. Suppose a program gets the same Substring over and over again. We can handle this case in code, and return a literal.

Here: I introduce simple code in SubstringFirst3 that optimizes the case of getting the first 3 letters of the string "Windows."

So: In a program that happens to do this operation many times, this logic would reduce allocations and increase speed.

C# program that avoids Substring using System; class Program { static string SubstringFirst3(string value) { // ... Use logic to avoid creating a new string. if (value == "Windows") { return "Win"; } else { return value.Substring(0, 3); } } static void Main() { Console.WriteLine(SubstringFirst3("Windows")); Console.WriteLine(SubstringFirst3("Computer")); } } Output Win Com

All substrings. Is one string contained in another? This can be answered with IndexOf. But we can also extract all possible substrings, put them in a Dictionary, and use ContainsKey.

And: This approach can be many times faster than using IndexOf, but only works in certain cases.

Dictionary: If we were to place these substrings in a Dictionary, use the substring for the key, and the original string for the value.


Important: Do not attempt this on a long string, or memory usage might explode. A tree data structure can be an even better solution.

Here: We generate all substrings for an input string. These substrings can be used as keys in a Dictionary.

C# program that generates all substrings using System; class Program { static void Main() { string value = "abcdefghi"; // Avoid full length. for (int length = 1; length < value.Length; length++) { // Be careful with the end index. for (int start = 0; start <= value.Length - length; start++) { string substring = value.Substring(start, length); Console.WriteLine(substring); } } } } Output a b c d e f g h i ab bc cd de ef fg gh hi abc bcd cde def efg fgh ghi abcd bcde cdef defg efgh fghi abcde bcdef cdefg defgh efghi abcdef bcdefg cdefgh defghi abcdefg bcdefgh cdefghi abcdefgh bcdefghi

Benchmark, char array. String-related allocations can be a burden. Here we see if taking characters and putting them into a char array is faster than calling Substring.

Version 1: This code creates a char array and assigns elements from the source string. Then it creates a string with a constructor.

Version 2: This version uses the Substring() method—it is shorter, simpler, and faster.

Result: Substring is faster. But if we want to extract only certain characters, consider the char array approach shown.

Char Array

Tip: It is best to use Substring when it has equivalent behavior. Code is shorter, simpler and easier to read.

C# program that benchmarks new string from char array using System; using System.Diagnostics; class Program { const int _max = 1000000; static void Main() { const string value = "onetwothree"; // Version 1: create new string from char array. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { char[] array = new char[3]; array[0] = value[3]; array[1] = value[4]; array[2] = value[5]; string result = new string(array); if (result == null) { return; } } s1.Stop(); // Version 2: use Substring. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string result = value.Substring(3, 3); if (result == null) { return; } } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } } Output 19.19 ns new char[], new string() 13.58 ns Substring

Benchmark, one char. Suppose we have a string and we want to get a single character from it. A 1-char substring is possible, but accessing the char directly is a better option.

Version 1: This code uses a 1-char substring call to get the first letter of the word "jounce."

Version 2: This version accesses the first character with an index expression. It performs faster.

Result: If your program creates 1-char substrings occasionally, it might be worth special-casing those calls to access a char instead.

C# program that tests one-char substring performance using System; using System.Diagnostics; class Program { const int _max = 1000000; static void Main() { const string value = "jounce"; // Version 1: get 1-character substring. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string firstLetter = value.Substring(0, 1); if (firstLetter != "j") { return; } } s1.Stop(); // Version 2: access char directly. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { char firstLetter = value[0]; if (firstLetter != 'j') { return; } } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } } Output 18.07 ns Substring, 1-char 0.99 ns Access char directly

Notation. Other languages use different arguments for substring. For example, in Java the start index and the end index are specified—the length of the substring is not needed.

Slice: In Python and JavaScript, slice notation is often used. We can use relative indexes.

An extension. We can add an extension method to "slice" strings. So you can specify indexes, as in Java or Python, to get substrings in your C# program.String Slice

Research. Here is some reference material on the Microsoft Docs site. I recommend using all resources possible to improve your knowledge.

Quote: Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.

String.Substring Method: Microsoft Docs

Rewrite Split. Internally the Split method finds Substrings and places them into a string array. With Substring and IndexOf we can duplicate this logic.Split

Sometimes: We only need a single part of a large string. If we avoid Split in this case, we can avoid creating many strings.

Bugs: This style of optimization can yield code that is fast but prone to bugs. Be prepared to fix problems.

First words. A string contains important words at its start. With a loop that counts spaces, we can extract the first words from a string into a new string.First WordsFirst Sentence

A summary. Substring() allocates a new string. We invoke it with 1 or 2 arguments—the start and length. Avoiding Substring when possible is often a worthwhile optimization.
Dot Net Perls
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to