Question
How can I split a C# string using another string, rather than a single character, as the delimiter?
For example, given this input:
"THExxQUICKxxBROWNxxFOX"
I want to split it using "xx" and receive an array containing:
THE
QUICK
BROWN
FOX
I tried converting the delimiter to a character array, but that did not produce the intended result.
Short Answer
You will learn how to use the string.Split overload that accepts string separators in C#. You will also see how multi-character delimiters differ from character delimiters, how to remove empty entries, and how this is commonly used when parsing simple structured text.
Concept
string.Split has multiple overloads. Some split text at individual characters, while others split text at whole strings.
To split by a multi-character delimiter such as "xx", pass an array of strings to Split:
string[] parts = text.Split(new[] { "xx" }, StringSplitOptions.None);
The new[] { "xx" } value is a string array containing one delimiter. The delimiter is treated as one complete sequence, not as two separate x characters.
This distinction matters because a character-based split interprets every character in the delimiter independently. For example, splitting by new[] { 'x' } means “split at every x,” not “split only when two consecutive x characters appear.”
String delimiters are useful when reading text formats that use markers such as "--", "::", "<br>", "||", or a custom token such as "[END]".
Mental Model
Think of a delimiter as a boundary marker in a document.
- A character delimiter is like being told: “Cut whenever you see the letter
x.” - A string delimiter is like being told: “Cut only when you see the exact stamp
xx.”
For THExxQUICK, splitting on the character x cuts at each individual x. Splitting on the string "xx" recognizes the two-letter stamp as one boundary and returns the words around it.
Syntax and Examples
Use the Split overload that accepts a string[] and a StringSplitOptions value:
string[] result = input.Split(
new[] { delimiter },
StringSplitOptions.None
);
Example:
using System;
string input = "THExxQUICKxxBROWNxxFOX";
string[] words = input.Split(new[] { "xx" }, StringSplitOptions.None);
foreach (string word in words)
{
Console.WriteLine(word);
}
Output:
THE
QUICK
BROWN
FOX
StringSplitOptions.None keeps empty strings if the delimiter appears at the beginning, end, or multiple times in a row.
For example:
string input = "THExxxxFOX";
string[] parts = input.Split(new[] { "xx" }, StringSplitOptions.None);
Console.WriteLine(string.Join(" | ", parts));
Output:
THE | | FOX
Use StringSplitOptions.RemoveEmptyEntries when empty values should be ignored:
string[] parts = input.Split(
new[] { "xx" },
StringSplitOptions.RemoveEmptyEntries
);
This produces:
THE | FOX
Step by Step Execution
Consider this code:
string input = "THExxQUICKxxBROWNxxFOX";
string delimiter = "xx";
string[] parts = input.Split(
new[] { delimiter },
StringSplitOptions.None
);
Execution steps:
inputholds the complete text:THExxQUICKxxBROWNxxFOX.delimiterholds the exact separator text:xx.new[] { delimiter }creates a string array containing one separator:["xx"].Splitscans the input from left to right for complete matches of"xx".- It finds the first
"xx"afterTHE, soTHEbecomes the first array item. - It finds the next delimiter after
QUICK, then another afterBROWN. - The remaining text,
FOX, becomes the final item.
The resulting array is equivalent to:
string[] parts = { "THE", "QUICK", "BROWN", "FOX" };
Real World Use Cases
Multi-character string delimiters appear in many practical tasks:
- Importing custom data files: A legacy export might use
"||"between fields. - Parsing composite configuration values: A setting such as
"host::port::database"can use"::"as the separator. - Processing simple log lines: A log may use
" --> "between a timestamp and message. - Separating user-entered tags: An application might accept tags separated by
", ". - Reading lightweight protocols: Internal tools sometimes use markers such as
"[NEXT]"or"<ITEM>".
For standardized formats such as JSON, CSV with quoted values, XML, or URLs, use a dedicated parser instead of manually calling Split. Those formats have rules that a simple delimiter split cannot fully handle.
Real Codebase Usage
In production code, developers usually validate text before splitting and choose options deliberately.
Validate the delimiter
An empty delimiter is usually an input error. A guard clause makes that clear:
static string[] SplitByDelimiter(string input, string delimiter)
{
if (string.IsNullOrEmpty(delimiter))
{
throw new ArgumentException("A delimiter is required.", nameof(delimiter));
}
return input.Split(new[] { delimiter }, StringSplitOptions.None);
}
Trim and discard empty fields
When parsing user input, fields may have extra spaces or repeated delimiters:
string input = " red || blue || || green ";
string[] colors = input
.Split(new[] { "||" }, StringSplitOptions.RemoveEmptyEntries)
.Select(color => color.Trim())
.ToArray();
This pattern uses:
RemoveEmptyEntriesto ignore blank pieces created by repeated separators.Trim()to remove surrounding whitespace.SelectandToArrayfrom LINQ to transform every result.
Limit the number of pieces
Some .NET versions provide overloads that accept a count. This is useful when only the first delimiter has structural meaning, such as separating a key from the rest of a value:
string input = "Title::A value::with more text";
string[] pieces = input.Split(
new[] { "::" },
2,
StringSplitOptions.None
);
The result is "Title" and "A value::with more text".
Common Mistakes
Splitting by each character instead of the full delimiter
This code does not mean “split by xx”:
string[] parts = input.Split(new[] { 'x', 'x' });
Split(char[]) sees individual characters. Repeating 'x' does not create a two-character delimiter.
Use:
string[] parts = input.Split(new[] { "xx" }, StringSplitOptions.None);
Calling the character overload accidentally
This works only for a single-character separator:
string[] parts = "a,b,c".Split(',');
It cannot accept "xx" because "xx" is a string, not a char.
Forgetting empty values
This input has two adjacent separators:
string input = "first||||third";
With "||" as the delimiter, the default result includes an empty item:
string[] parts = input.Split(new[] { "||" }, StringSplitOptions.None);
// "first", "", "third"
Choose RemoveEmptyEntries only if an empty field is not meaningful.
Assuming Split trims whitespace
Split separates text but does not remove spaces:
string input = "red || blue";
string[] parts = input.Split(new[] { "||" }, StringSplitOptions.None);
// "red ", " blue"
Trim the results if needed:
string[] cleanParts = parts.Select(part => part.Trim()).ToArray();
Using Split for complex file formats
A CSV value may legally contain commas inside quotes, such as:
"Smith, Jane",42
A simple comma split would break this incorrectly. Use a CSV parser for CSV data.
Comparisons
| Approach | Delimiter type | Example | Best use |
|---|---|---|---|
Split(char) | One character | text.Split(',') | Simple separators such as commas or spaces |
Split(char[]) | Any one of several characters | text.Split(new[] { ',', ';' }) | Split on commas or semicolons |
Split(string[], StringSplitOptions) | One or more complete strings | text.Split(new[] { "xx" }, StringSplitOptions.None) | Multi-character markers such as "xx" or `" |
Regex.Split | Pattern | Regex.Split(text, "x+") | Variable or rule-based separators |
A char[] means “any of these individual characters.” A string[] means “any of these complete text sequences.”
Use Regex.Split only when the separator is truly a pattern. For a fixed delimiter such as "xx", normal string.Split is simpler and clearer.
Cheat Sheet
// Split on one character
string[] items = text.Split(',');
// Split on several individual characters
string[] items = text.Split(new[] { ',', ';' });
// Split on one multi-character string
string[] items = text.Split(
new[] { "xx" },
StringSplitOptions.None
);
// Split on several complete strings
string[] items = text.Split(
new[] { "--", "::", "||" },
StringSplitOptions.None
);
// Ignore empty pieces
string[] items = text.Split(
new[] { "||" },
StringSplitOptions.RemoveEmptyEntries
);
// Trim each split result
string[] cleaned = text
.Split(new[] { "||" }, StringSplitOptions.RemoveEmptyEntries)
.Select(item => item.Trim())
.ToArray();
Key rules:
- Use
charorchar[]for character separators. - Use
string[]for multi-character separators. StringSplitOptions.Nonepreserves empty entries.StringSplitOptions.RemoveEmptyEntriesremoves empty entries.Splitdoes not trim whitespace automatically.
FAQ
Can string.Split use a string delimiter in C#?
Yes. Pass a string[] containing the delimiter:
text.Split(new[] { "xx" }, StringSplitOptions.None);
Why does Split(new[] { 'x', 'x' }) not split by "xx"?
Because that uses the character-array overload. It treats each 'x' as an independent separator, rather than looking for the exact sequence "xx".
How do I split by more than one string delimiter?
Put each complete delimiter in the string array:
text.Split(new[] { "--", "::" }, StringSplitOptions.None);
What happens if delimiters appear next to each other?
With StringSplitOptions.None, Split returns an empty string for the text between them. Use RemoveEmptyEntries to discard it.
Does Split remove spaces around each item?
No. Call Trim() on each result when whitespace should be removed.
Is string splitting case-sensitive?
The standard Split overloads match delimiters exactly and are case-sensitive. If you need case-insensitive or more flexible matching, consider Regex.Split or other parsing logic.
Should I use Split to parse CSV files?
Usually no. CSV supports quoted fields, escaped quotes, and delimiters inside values. Use a CSV parser instead.
Mini Project
Description
Build a small parser for a custom category field. An administrator enters product categories in one text value using "||" as the separator. The parser should return clean category names even when the input contains spaces or accidental repeated separators.
Goal
Create a method that splits a "||"-separated string into a cleaned array of category names.
Requirements
Use "||" as a multi-character string delimiter.
Ignore empty values caused by repeated or leading/trailing delimiters.
Remove whitespace around each category name.
Reject a null or whitespace-only input value.
Print the cleaned categories to the console.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.