Handling Casing Issues though Extension Methods in C# and Visual Basic

If you have ever worked extensively with any kind of system that involves names, addresses or basically any kind of arena that allows users to enter data, then you might find this helpful.

Users often don’t have any concern with how things might appear within an application and there may be a few situations where you want to actually properly format some of your input. Using some of the existing methods that are available in .NET, we can handle some of the more basic casing-related needs (such as upper-casing and lower-casing a string) but your business needs may require some more complex methods to handle this.

This can be accomplished in a variety of ways, but in this post, we will leverage extension methods to help keep our code relatively clean.

Lower-casing

Lowercase

One of the easiest methods to handle is simply taking a string and transforming all of the existing letters into their lower-case brethren. This can easily be done using the String.ToLower() or String.ToLowerInvariant() methods as seen below :

// Example 1: ToLowerCase (all lower-case)
var lowercase = "This is an example".ToLowerInvariant(); // yields "this is an example"  

Upper-casing

Upper-casing

Another commonly encountered method is the requirement to switch all of the letters within a string to their upper-case form. This is accomplished through the String.ToUpper() or String.ToUpperInvariant() method and is perfect when you need to yell at someone.

// Example 2: ToUpperCase (all upper-case)
var uppercase = "This is an example".ToUpperInvariant(); // yields "THIS IS AN EXAMPLE"  

Title-casing (Pascal or Sentence-casing)

Title-casing

Title-casing is method of casing that as the name implies would focus on capitalizing the first letter of all of the words within a string. This would most commonly be used some instances involving proper names, titles and can be a bit trickier to implement that its upper and lower-case brethren.

Commonly, you would use the TextInfo.ToTitleCase() method to handle this as follows :

// Example 3: ToTitleCase (upper-cases the first letter of each word)
var nottitled = CultureInfo.InvariantCulture.TextInfo.ToTitleCase("THIS IS AN EXAMPLE");  

But you’ll notice a minor flaw in the TextInfo.ToTitleCase() method as it does not convert upper-case characters to lower-case (they are considered to be acronyms). This can be a problem that can be easily fixed by simply using the String.ToLower() or String.ToLowerInvariant() methods on your target string :

// Example 3a: ToTitleCase
var nottitled = CultureInfo.InvariantCulture.TextInfo.ToTitleCase("THIS IS AN EXAMPLE".ToLowerInvariant());  

or if you wanted to make an extension method for it, you would simply use :

public static class StringExtensions  
{
       public static string ToTitleCase(this string s)
       {
               return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(s.ToLowerInvariant());
       }
}

which would be used as :

// Example 3a: ToTitleCase (as an extension method)
var titlecase = "THIS IS AN EXAMPLE".ToTitleCase(); / yields "This Is An Example"  

You will need to include the appropriate namespace to have access to the TextInfo object, but you just need to add the following using statement to your code :

// Necessary for TextInfo (used in ToTitleCase)
using System.Globalization;  

Camel-casing (basically Title-casing with the first letter being lower-cased)

Camel-casing

Camel-casing is commonly used within naming conventions to denote some variables such as engineType, vogonPoetry, anotherVariableName. It is probably less commonly encountered with strings, however we will review over handling it in case the need arises. This example is specifically for space or otherwise delimited words, as you would need to add quite a bit additional logic to match the beginning of actual words within a single string.

Camel-casing is basically going to be implemented the same way as Title-casing with the exception that we will always explicitly set the first letter to lower-case as seen below :

public static string ToCamelCase(this string s)  
{
       // Build the titlecase string
       var titlecase = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(s.ToLowerInvariant());
       // Ensures that there is at-least two characters (so 
       // that the Substring method doesn't freak out)
       return (titlecase.Length > 1) ? Char.ToLowerInvariant(titlecase[0]) + titlecase.Substring(1) : titlecase;
}

which would be used as :

// Example 4: ToCamelCase (basically ToTitleCase except the first character is lowercased)
var camelcase = "This is an example".ToCamelCase(); // yields this Is An Example"  

Irish-Casing (capitalizing characters that follow apostrophes such as O’Reilly, etc. )

Irish-casing

In another format that you might occasionally encounter the need for capitalizing the letters that occur after apostrophes (such as in Irish or Gaelic names) which we will call "Irish-case". We will assume that this will primarily be used on names, so it will just involve them being changed into Title-case and then we will use a Regular Expression to match each of the characters that occur after an apostrophe and replace them with their upper-case variant. Prior to going into these, you’ll also need to include another namespace reference since you will be working with Regular Expressions :

// Necessary for Irish and Custom-casing
using System.Text.RegularExpressions;  

After including that, you can easily add in the following code and get started :

public static string ToIrishCase(this string s)  
{
       // This will build a Titlecased string, but 
       // will uppercase any letter's that appear after
       // apostrophes (as in names)
       var titlecase = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(s.ToLowerInvariant());
       // Replaces any character after an apostrophe 
       // with its uppercase variant
       return Regex.Replace(titlecase, "'(?:.)", m => m.Value.ToUpperInvariant());
}

which would be used again as an extension method :

// Example 5: Special Casing for names
var irishcase = "O'reilly".ToIrishCase(); // yields "O'Reilly"  

Irish-casing is interesting because it can easily be elaborated on or added to. For instance, if you wanted to add this same logic to not only match characters that occurred after apostrophes but hyphens as well, you would just need to adjust the expression being used from :

'(?:.)  

to :

['-](?:.)

The expression will now match both of these characters and capitalize accordingly :

public static string ToExtendedIrishCase(this string s)  
{
       // This will build a Titlecased string, but will 
       // uppercase any letter's that appear after 
       // apostrophes (as in names)
       var titlecase = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(s.ToLowerInvariant());
       // Replaces any character after an apostrophe or 
       // hyphen with its uppercase variant
       return System.Text.RegularExpressions.Regex.Replace(titlecase, @"['-](?:.)", m => m.Value.ToUpperInvariant());
}

and an example might look like this :

// Example 5a: ToExtendedIrishCase (like Irishcase, 
// but it also captializes characters after hyphens as well)
var irishcase = "kathleen hely-hutchinson".ToIrishCase(); // yields "Kathleen Hely-Hutchinson"  

This probably serves an excellent segue to our next and most custom extension method, Custom-casing.

Custom-Casing (provides the lower-cased version of a string with only the characters specified being upper-cased)

Custom-casing

Custom-casing would be a method that might function as a starting-point if you wanted to write your own completely custom form of casing if the need arises. In this example of Custom-casing, the method is going to transition all of the characters to lower-case variants and then it will use an expression to match only the characters specified and change them into upper-case ones :

public static string ToCustomCasing(this string s, string[] characters)  
{
       // If there are no characters to specifically capitalize,
       // return the initial string
       if (characters == null || !characters.Any())
       {
              return s;
       }
       // Replacement expression
       var replacements = String.Format("[{0}]", String.Join("", characters).ToLowerInvariant());
       // Replaces any characters that were passed in
       return System.Text.RegularExpressions.Regex.Replace(s.ToLowerInvariant(), replacements, m => m.Value.ToUpperInvariant());
}

which would look like this when used :

//Example 6: Custom Casing (only upper-cases specific characters)
var customcase = "This is an example".ToCustomCasing(new string[] { "e", "i" }); // yields "thIs Is an ExamplE"  

Overview & Code Examples

These are just a few methods that might help you solve some tricky issues or implement specific conventions when dealing with user or otherwise generated input within your applications. The use of extension methods provides a very clean approach and the methods themselves are quite straight-forward and should be easy to extend if a specific need arises.

You can download all of the examples that were specified within this post in both C# and Visual Basic from the following repository on GitHub :

comments powered by Disqus