C# String
In this article I will discuss about the C# string type which is a very important to understand as strings are everywhere in C# programming. The article will go through about type of string, then we will check about some of the important functions which we should be aware of while working on string manipulations. Going further we will check about the null reference checking and string literals.
String is reference type
String in C# are reference type. Reference type and value type can be studied here. Since strings are array of character it is usually difficult to tell the size of the string while initializing it which in turn have complex working to store it on the stack memory(where the value types are kept) if strings were value type. This is the main reason to treat strings as reference type.
Interesting Anomaly with string reference comparison
To compare two references we use Equal method of object class. Before going further lets check the code below.
var person1 = new Person() { FirstName = "David" }; var person2 = new Person() { FirstName = "David" }; Console.WriteLine(object.Equals(person1, person2));//false string strName = "David"; string strName1 = "David"; Console.WriteLine(object.Equals(strName, strName1));//true
In the above code I am comparing the two reference of the Person class which is returning false as we know whenever we create a reference it is allocated a new memory location in the heap. That is what is happening in first case where we are comparing two different references.
But in the second case where we are comparing two string instances but still we are getting the result as true. The reason for this is thatCLR checks that if there is already a string with the same value and it will refer the same string instead of creating a new reference. Please note that this comparison is case sensitive.
String are Immutable
Strings are reference type but they are made immutable to be treated as value types. Please check the below code.
string name = " David "; Console.WriteLine(string.ReferenceEquals("David", name.Trim()));//False
The above code should have returned the value as true as per the discussion above but since name.Trim() returns a new reference, the above code returns a false value.
Due to this behaviour of strings it is costly to use strings where we are working with lots of string concatenation or manipulation, as each and every action on string results in new reference creation.
To work more effectively with string concatenation and manipulation StringBuilder class has been introduced. You can check here why StringBuilder is better in performance.
Important String Instance Methods
Here I will brief about some of the important methods of string class.
- ToUpper() – Converts all the characters of the string to Upper case.
- ToLower() – Converts all the characters of the string to Lower case.
- SubString() – Extracts the sub string from the string, based on the start index and count of characters.
- IndexOf() – returns the index of particular character appearance.
- Trim() – Trims the white space from the start and end of the string.
- Split() – Splits the string based on the character passed and return an array of strings.
ToUpper() and ToLower() are overloaded to accept culture invariance as one of the parameters. ToLower() and ToUpper() without this parameter will change the string based on the end users local culture which can lead to bugs in code. If we want to convert string irrespective of the users culture we should use the code as shown below
string name = @"I am the ""best"" Developer"; name.ToLowerInvariant(); name.ToUpperInvariant(); name.ToLower(CultureInfo.InvariantCulture); name.ToUpper(CultureInfo.InvariantCulture);
Culture Invariant Comparison
if I run the below code I will be getting true for comparing the two C# strings. My system’s current culture i.e. en-US, the comparison is correct.
const string strlocal = "I AM BEST DEVELOPER"; public static void Main() { string fromDB = "i am best developer"; bool result = string.Equals(fromDB.ToUpper(), strlocal);//returns true }
In the above code I am comparing the strlocal which in a const C# string variable with fromDB string variable. We can guess that we are getting the fromDBs value from some external source.
But if I change the current culture of my system to Turkey as Shown below.
const string strlocal = "I AM BEST DEVELOPER"; public static void Main() { Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("tr"); string fromDB = "i am best developer"; bool result = string.Equals(fromDB.ToUpper(), strlocal);//returns false }
The result of code is false as fromDB.ToUpper() is converted to “İ AM BEST DEVELOPER” in turkey culture. Please note extra .(dot) on top of (I) character which results in negative result.
To prevent ourselves from these kind of bugs we should use culture invariant comparison. In this case we should use ToUpperInvariant() and we will get correct result.
Important String Static Methods
- string.Concat
- string.Join
These are the two methods of C# string class which every programmer should be aware of as it can prevent us from the nasty foreach loops while joining or concatenating the string from collection as shown in the below code.
IList<string> names = new List<string>() {"Test", "test1", "Test2" }; string concat = string.Concat(names);
and
Person per1 = new Person() { Name = "test", Age = 2 }; Person per2 = new Person() { Name = "test1", Age = 4 }; Person per3 = new Person() { Name = "tset2", Age = 6 }; IList<Person> names = new List<Person>(); names.Add(per1); names.Add(per2); names.Add(per3); string test = string.Join(",", names.Where(p => p.Age > 3));
where Person is a class having name and age property.
Checking null reference and String Emptiness
While working with string there are many chances that we have to compare the string for null reference or Empty string.
In the above figure I am checking for the string null and emptiness using two methods. Since the first method i.e. IsNullOrEmpty doesn’t check for the white spaces that is why the first method is returning false while IsNullOrWhiteSpace return true for the same string as it checks for white spaces.
in C# 6.0 we have one more reference check operators for string reference checks and that is the null conditional operator for strings as shown in the below code
string name = null; string lowercase = name?.ToLower();
The above code does not throw an exception while we change the string to lower case even if it is null.
String Literal Verbatim
There are chances that we want to have some escape characters in our string which help us to start a new row(\n) , insert a tab(\t) etc. But there are chances that these can be the part of the string only.
In these cases we have to start the code with @ character if we want to include \r, \n, \t or \ in the string for example while specifying file and folder names or to include double characters in the string as shown in the below code
string name = @"I am the ""best"" Developer"; Console.WriteLine(name);
String Interpolation
We can interpolate the strings using the below shown syntax using Format method of string class which help our code to look better and more readable.
string firstname = "vikram"; string lastname = "chaudhary"; Console.WriteLine(string.Format("My name is {0} {1}", firstname, lastname));
The string interpolation can be achieved in C# 6.0 by using the below syntax just by having $ character at the start of the string.
string firstname = "vikram"; string lastname = "chaudhary"; Console.WriteLine($"My name is {firstname} {lastname}");
Conclusion
C# string type is used widely in programming and learning the small details about string class can help us to make our code clear and easily understandable.