C# 3.0 Features: Extension Methods
.NET 3.5 is out which means all of the great features available in C# 3.0 are available to use now. Here's a quick list of the main language enhancements available in C# 3.0:
Extension methods allow existing classes to be extended without relying on inheritance or having to change the class's source code. This means that if you want to add some methods into the existing String class you can do it quite easily. Here's a couple of rules to consider when deciding on whether or not to use extension methods:
-
Extension methods cannot be used to override existing methods
-
An extension method with the same name and signature as an instance method will not be called
-
The concept of extension methods cannot be applied to fields, properties or events
-
Use extension methods sparingly....overuse can be a bad thing!
Here's an example of creating an extension method in C# that adds a RemoveNonNumeric() method to the String class. Notice that the class is defined as static as well as the extension method itself. The "this" keyword in the parameter signature tells the compiler to add the extension method to the String class since "string" follows the keyword.
namespace StringExtensions { public static class StringExtensionsClass { public static string RemoveNonNumeric(this string s) { MatchCollection col = Regex.Matches(s, "[0-9]"); StringBuilder sb = new StringBuilder(); foreach (Match m in col) sb.Append(m.Value); return sb.ToString(); } }
Here's an example of how the extension method can be used. You'll see that the namespace for the extension method class is imported. From there, the compiler treats the RemoveNonNumeric() method as if it was originally part of the standard System.String class.
using StringExtensions;
.... string phone = "123-123-1234"; string newPhone = phone.RemoveNonNumeric();
Update: Although the overall point of the post was to simply show how to create extension methods, Andrex posted a more efficient way to remove non-numeric characters for those that may actually need that specific functionality (I'll admit I was just throwing something out there :-)). Thanks for commenting Andrex!
public static string RemoveNonNumeric(this string s) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.Length; i++) if (Char.IsNumber(s[i])) sb.Append(s[i]); return sb.ToString(); }
Update 2: Richard posted the following method which is potentially even faster according to his tests. We're kind of pulling hairs here, but it's useful for "anyone who agonizes over every wasted millisecond" as he mentions in the comments (I'm not one of those people :-)). I'm thinking I should start a "How would you refactor this code" series. Could be kind of fun. :-)
public static string RemoveNonNumeric(this string s) { if (!string.IsNullOrEmpty(s)) { char[] result = new char[s.Length]; int resultIndex = 0; foreach (char c in s) { if (char.IsNumber(c)) result[resultIndex++] = c; } if (0 == resultIndex) s = string.Empty; else if (result.Length != resultIndex) s = new string(result, 0, resultIndex); } return s; }