Yay! I finally have an excuse to use extension methods.
First, a brief explanation of what they are. Suppose you
have an object – say a string. And you want to add some functionality to it.
You could subclass the object (assuming it’s not sealed) and add your new
method.
But if all you want to do is add one tiny little method,
subclassing seems a bit top-heavy, doesn’t it? Besides, unless you’re using an
object factory pattern (my favorite design pattern, by the way), you face the
prospect of finding and changing every object instantiation in every line of
code of your project to replace the parent with the child class. On large,
multiple developer projects, this gets rough.
Microsoft gives you a work around. What you can do is to add
a special static method somewhere in your code and .Net will automagically assign
this to the desired class.
For example,
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
The magic is the keyword “this” in the method signature. “This”
tells the compiler that “WordCount” is an extension method on the string
object.
The end result is that your code can now do something like:
string x = "this is a test string";
Console.WriteLine(x.WordCount());
And the Console will show the word count of x, just as if “WordCount”
was a public method on the string class.
I’ve thought this was cool for a long time, but couldn’t
find a use for it.
But, Dmytrii Nagirniak posted a reply to a
thread on Stack Overflow that provides an awesome use:
http://stackoverflow.com/questions/1725903/determine-if-datacolumn-is-numeric
To sum it up, .Net has no “IsNumber()” method. So looking at
a potential data value, it’s really hard to know if it’s a number type. What
you end up with, is a complex if statement that does a GetType(), but then has
to check to see if the type is a Double OR a Single OR an Int32 OR an Int64 OR a
UInt16 OR…. Etc.
Putting this into an extension method makes a ton of sense. (I’m not sure why Microsoft didn’t already do this, frankly). This means that developers don’t need to deal with this mess each time, but just have to call
x.IsNumber().
The code for the extension just looks like this:
public static Type[] numericTypes = new[] { typeof(Byte), typeof(Decimal), typeof(Double),
typeof(Int16), typeof(Int32), typeof(Int64), typeof(SByte),
typeof(Single), typeof(UInt16), typeof(UInt32), typeof(UInt64)};
public static bool IsNumber(this object x)
{
if (x == null)
return false;
return numericTypes.Contains(x.GetType() );
}
And this allows you
to instantiate any object and define whether the object is a number type.
A second (useful) variation of this examines whether a DataColumn
(ie, in a DataTable) is a number type. It’s different because the DataColumn.GetType()
would just return “DataColumn, you moron”, so you have to look at “DataColumn.DataType”
:
public static bool IsNumeric(this DataColumn col)
{
if (col == null)
return false;
return numericTypes.Contains(col.DataType);
}
Pretty cool stuff.
--kevin
No comments:
Post a Comment