String Extension Methods: Introduction
For better or worse, a lot of my life as a developer is spent writing code to manipulate strings. I perform the same operations so frequently I have (along with my coworkers) come up with some handy string extension methods that you might find useful as well. If you are unfamiliar with extension methods, you should start down the path to enlightenment here before continuing with this post.
String Extension Methods: IsEmpty
The string class exposes a handy static method called IsNullOrWhiteSpace. I like to be able to call this method as an extension method for convenience sake. I don’t think a day goes by where I don’t use this method and it will become second nature to you in no time.
The Method
/// <summary>
/// Check to see if a string is empty. We define empty as null, string.Empty or whitespace (so our method name isn't incredibly long).
/// </summary>
/// <param name="str">The string to check.</param>
/// <returns>A bool field that will be true if the string is null, empty or whitespace.</returns>
public static bool IsEmpty(this string str)
{
return string.IsNullOrWhiteSpace(str);
}
Usage
string testString = "The quick brown fox jumps over the lazy dog";
string emptyString = string.Empty;
string nullString = null;
Console.WriteLine(string.Format("'{0}' is empty: {1}", testString, testString.IsEmpty())); // False
Console.WriteLine(string.Format("'{0}' is empty: {1}", emptyString, emptyString.IsEmpty())); // True
Console.WriteLine(string.Format("'{0}' is empty: {1}", nullString, nullString.IsEmpty())); // True
Left / Right
If you have a background in VB (and who doesn’t love and/or have some history with VB?) you will probably be used to these methods. I have ported my fair share of VBA to C# and these methods come in handy. VBA porting aside, it’s nice to be able to grab a substring without worrying about checking length (since the extension method does that for you).
The Methods
/// <summary>
/// Returns the specific number of characters from the start of the string.
/// </summary>
/// <param name="str">The string to take from.</param>
/// <param name="numberOfCharacters">The number of characters to take.</param>
/// <returns>A string of the specified length.</returns>
public static string Left(this string str, int numberOfCharacters)
{
if (str.IsEmpty())
return string.Empty;
if (str.Length > numberOfCharacters)
str = str.Substring(0, numberOfCharacters);
return str;
}
/// <summary>
/// Returns the specified number of characters from the end of the string.
/// </summary>
/// <param name="str">The string to take from.</param>
/// <param name="numberOfCharacters">The number of characters to take.</param>
/// <returns>A string of the specified length.</returns>
public static string Right(this string str, int numberOfCharacters)
{
if (str.IsEmpty())
return string.Empty;
if (str.Length > numberOfCharacters)
str = str.Substring(str.Length - numberOfCharacters, numberOfCharacters);
return str;
}
Usage
string testString = "The quick brown fox jumps over the lazy dog";
Console.WriteLine(string.Format("Left 9 test: {0}", testString.Left(9))); // Returns "The quick"
Console.WriteLine(string.Format("Right 8 test: {0}", testString.Right(8))); // Returns "lazy dog"
IsInt / IsLong / IsDecimal
A lot of VB/VBA people complain that there is no IsNumeric method in C#. While IsNumeric might be useful to some (and easily accomplished via a regular expression or other means), I am usually checking to see if a string is of a certain numeric data type before casting it to manipulate it or store it in a database. To that end, I have broken up the idea of IsNumeric in to IsInt, IsLong and IsDecimal.
The Methods
/// <summary>
/// Returns true if a string is an int.
/// </summary>
/// <param name="str">The string to check</param>
/// <returns>A bool value indicating whether or not this string is an int.</returns>
public static bool IsInt(this string str)
{
int dummyInt;
return int.TryParse(str, out dummyInt);
}
/// <summary>
/// Returns true if a string is a long.
/// </summary>
/// <param name="str">The string to check</param>
/// <returns>A bool value indicating whether or not this string is a long.</returns>
public static bool IsLong(this string str)
{
long dummyLong;
return long.TryParse(str, out dummyLong);
}
/// <summary>
/// Returns true if a string is a decimal.
/// </summary>
/// <param name="str">The string to check</param>
/// <returns>A bool value indicating whether or not this string is a decimal.</returns>
public static bool IsDecimal(this string str)
{
decimal dummyDecimal;
return decimal.TryParse(str, out dummyDecimal);
}
Usage
string intString = int.MaxValue.ToString();
string longString = long.MaxValue.ToString();
string decimalString = decimal.MaxValue.ToString();
string doubleString = double.MaxValue.ToString();
Console.WriteLine(string.Format("{0} is int: {1}", intString, intString.IsInt())); // True
Console.WriteLine(string.Format("{0} is int: {1}", longString, longString.IsInt())); // False
Console.WriteLine(string.Format("{0} is int: {1}", decimalString, decimalString.IsInt())); // False
Console.WriteLine(string.Format("{0} is int: {1}", doubleString, doubleString.IsInt())); // False
Console.WriteLine("------");
Console.WriteLine(string.Format("{0} is long: {1}", intString, intString.IsLong())); // True
Console.WriteLine(string.Format("{0} is long: {1}", longString, longString.IsLong())); // True
Console.WriteLine(string.Format("{0} is long: {1}", decimalString, decimalString.IsLong())); // False
Console.WriteLine(string.Format("{0} is long: {1}", doubleString, doubleString.IsLong())); // False
Console.WriteLine("------");
Console.WriteLine(string.Format("{0} is decimal: {1}", intString, intString.IsDecimal())); // True
Console.WriteLine(string.Format("{0} is decimal: {1}", longString, longString.IsDecimal())); // True
Console.WriteLine(string.Format("{0} is decimal: {1}", decimalString, decimalString.IsDecimal())); // True
Console.WriteLine(string.Format("{0} is decimal: {1}", doubleString, doubleString.IsDecimal())); // False
Summary
This is just a small sample of extension methods that I find to be useful but once you start looking around your projects with an extension method-shaped hammer you will find nails all over the place. Before you jump off the deep end and create 50 new methods, here’s a word of caution: when working on a team it is of vital importance to communicate when you create a new extension method. Your teammates can’t benefit from your genius time-saving methods if they don’t know they exist and it also gives them a chance to hassle you, point out flaws in your logic (which is always fun!) and point out methods in the .Net framework that already accomplish what you are trying to do (which has never happened to me of course).