It?s time for yet another discussion on an important C# construct: the C# string.
String bears many similarities with other C# types. Like the C# array and list, you can think of the string as a collection or sequence of items, since string implements IEnumerable?and a number of other interfaces.
Like enum values, strings are often used as label cases in switch statements (even though in this case, strings are probably not the best option.)
Like DateTime, the string is an essential concept in programming, implemented as an immutable data type, and often misunderstood. Such misunderstandings can confuse the developers on your team, cause defects, and slow down development.
Would you want that?
Yeah, didn?t think so.
So, that?s what today post is about: educating developers about the C# string in the hope that such education can lead to better code.
- We?ll start by giving you a quick definition of the C# string.
- Then we?ll jump right in to examples of how to use the string type.
- And, along the way, we’ll look at best practices and warn you of possible pitfalls.
Let?s get started!
C# String: A Quick Definition
The string is one of the most fundamental data types out there.
Most often than not, it’s the first type a person ever uses when learning how to program. The bulk of the first programs ever written more or less simply display some text on the screen, after all.
Why “string” though?
You can dig into the history of the term if you have the time and feel like it. Here goes the TL;DR; version: string stands for?”string of characters”?or an ordered sequence of characters.
The C# string is backed up by the System.String?class in the .NET BCL, which is an immutable class that represents text as a sequence of System.Char elements.
Creating a C# String: Let’s Count the Ways
There are a lot of ways to create a new string. We’ll now quickly cover each one of them.
1. Assignment
The first way you certainly know and use. It’s just assigning a string literal to a variable like so:
string message = "Hello World!";
2. Using a Constructor
You can create a string by using one of the several constructor?overloads. One of them lets you create a string by passing an array of char:
char[] letters = { 'H', 'e', 'l', 'l', 'o', '!' }; string word = new string(letters); Console.WriteLine(word); // prints "Hello!"
Another option allows you to create a string from a given character, repeated n times:
string tenExclamationMarks = new string('!', 10); Console.WriteLine(tenExclamationMarks); // prints "!!!!!!!!!!"
There are six other overloads?that we won’t cover here for the sake of brevity.
3. Using Methods or Properties That Return String
Yet another way of getting a brand new C# string: just call a method or property that returns one.
The System.String class itself has many methods that return new instances, such as Replace, ToUpper, ToLower and many more. We’ll cover those soon. But here’s a quick example using “Replace”:
string s = "05/25/1977"; string s2 = s.Replace('/', '.'); Console.WriteLine(s2); // prints "05.25.1977"
4. Using Methods That Return the Textual Representation of an Object
Since every single object in C#/.Net descends from System.Object, they all have this method called ToString() which returns their textual representation:
double d= 10; string tenDollars = d.ToString("C", new System.Globalization.CultureInfo("en-US")); Console.WriteLine(tenDollars); // prints "$10.00";
This also happens when you use composite formatting:
double d = 1500; DateTime someDate = new DateTime(2018, 4, 1); System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); string message = string.Format("Today is {0:D} and your balance is {1:C}", someDate, d); // if your culture is set to "en-US", the result will be "Today is Sunday, April 01, 2018 and your balance is $1,500.00"
5. Using Concatenation
The C# string is immutable, remember?
Every time it seems like you’re tweaking, cutting, joining or otherwise changing a string instance, what’s really happening is you’re creating one or more instances.
So, using concatenation is obviously yet another way of instantiating new strings. The example below shows a string concatenation through the use of the ?+? operator:
string name = Console.ReadLine(); string message = "Hi, " + name + "! Welcome to our new app!";
C# String: Common Operations
We’ve seen the definition of the C# string. We then covered how to create a new one.
Now it’s time to show what this thing can do.
Or rather, what you can do with it.
We’ll list the most common operations you generally do with a string and explain how to make it happen.
Retrieving the Size
One of the most common operations you can do with the C# string (or a string in any language, for that matter) is get its size. In C#, just use the “Length” property:
int length = new string('!', 10).Length;
Best Practice: Even though the System.String class implements IEnumerable<char>, which means you could use the “Count()” LINQ extension method to retrieve its length, stick to the Length property.
Getting a Single Character
To retrieve a single character of a string, you must provide it the zero-based index of the character you want:
string message = "Hello World!"; char thirdLetter = message[2];
Pitfall: In the same way that happens with array and lists, the C# string will throw if you provide an invalid index. You have to be careful.
Checking Whether It Contains Another String
If you need to verify whether a string contains another one, the “Contains” method has your back:
string message = "Hello World"; bool containsHello = message.Contains("Hello"); Console.WriteLine(containsHello); // prints "True"
Pitfall: The “Contains” method performs a comparison that is case-sensitive and culture-insensitive. Passing “hello” as an argument would’ve resulted in false, for instance. If what you need is a comparison that ignores case and/or considers culture, you’ll have to use a custom method.
Splitting a String Based on a Delimiter
Imagine you have a series of email addresses in the format “user@domain” and you need to get just the domains. One answer to this would be the “Split” method:
string email = "someuser@example.com"; string[] parts = email.Split('@'); string user = parts[0]; string domain = parts[1];
In its simplest and most common overload, the “Split” method takes one or more characters as parameters and returns a string array, containing as many elements as there are pieces in the string delimited by the given separators.
Pitfall: If the string you want to split ends with the delimiter (or has white space after it), the resulting array will contain an element with empty or white space. This can be unexpected and cause bugs. If you want to ignore white space when splitting, use the following overload of the “Split” method:
string numbers = "10,5,2,78,23,1,5,"; string parts = numbers.Split( new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
Best Practice: When the string to be delimited comes from an external source (e.g., the filesystem), you can’t guarantee that it will have the number of parts you expect?or even if it’s going to contain the delimiter at all. Always check if the result arrays have the number of elements you expect it to have before trying to retrieve its numbers. Otherwise, you risk providing an invalid index and getting an exception.
Performing Replacements
When you need to replace one or more occurrences of a given character in a C# string, the answer is, unsurprisingly, a method called “Replace”.
The method has two overloads: one that takes two char parameters and another that takes two strings.
The following listing contains some examples of both versions:
string greetings = "Hi! My name is Carlos and I'm a ptogrammer."; Console.WriteLine(greetings.Replace('t', 'r')); // prints "Hi! My name is Carlos and I'm a programmer". string message = "I love Java!"; message = message.Replace("Java", "C#"); Console.WriteLine(message); // prints "I love C# string goodFellow = "For he's a jolly good yellow, for he's a jolly good yellow, For he's a jolly good yellow... which nobody can deny!"; string correct = goodFellow.Replace("yellow", "fellow"); Console.WriteLine(correct); // prints the correct lyrics; all instances of the word are replaced. Console.ReadLine();
Pitfall: As with “Contains,” the “Replace” method performs an ordinal comparison, i.e., case-sensitive and culture-insensitive. If you need another type of comparison, it makes sense to use a custom extension method.
Pitfall: Since the C# string is immutable, replace and similar operations are never performed in-place but always return a new instance. A common mistake beginners make is to forget to attribute the result of the method to a variable, which will gladly compile but will introduce inconsistent behaviors to the application.
Back to You
The C# string is definitely a very fascinating type; this post barely scratched the surface.
For instance, we haven’t covered anything related to the comparison of strings. This topic alone could make for several posts.
So now it’s back to you. Use the information we’ve passed along here as a starting point. But never stop studying and practicing. Don’t fall in the trap of programming by coincidence and you’re in for a great career in software development.
You might also be interested in further reading about other C# language concepts:
Learn more how CodeIt.Right can help you automate code reviews and improve the quality of your code.
8 Comments. Leave new
Well written, thanks for sharing! I’ve definitely run at least one pitfall you’ve outlined, particularly with Replace (and forgotten to handle assigning the output to a new variable so I could actually use it).
Hey Michael, thanks for your comment. I think we’ve all been bitten by this one at least once, right?
[…] C# String: Definition, Examples, Best Practices, and Pitfalls – Carlos Schults […]
Nice article, especially for beginners. Might be a good idea to talk about StringBuilder too?
Hi David. Thanks for your suggestion. And yes, we can definitely cover StringBuilder in the future.
[…] C# String: Definition, Examples, Best Practices, and Pitfalls […]
Another, more modern approach to string concatination or string.format is string interpolation.
var name = “John”;
Console.Writeline($”Hello, my name is {name}”);
See StringComparer.OrdinalIgnoreCase.