Showing posts with label Extension methods. Show all posts
Showing posts with label Extension methods. Show all posts

Wednesday, December 23, 2009

Useful Extension methods

I've posted in the past about the hazards in extension methods and how they can be easily abused. there are plenty of links out there specifying the cons of using this feature.
However, since the title got you in here, I'm assuming you are still interested.
I wanted to share some of the most common extension methods I use when writing code.

IsNullOrEmpty - I think we all know this method from the String class. Why not have the same capability on collections?
I did see plenty of samples on the web showing how to add this method to collections or arrays.
things like:
public static bool IsNullOrEmpty(this ICollection collection)
{
    return collection == null || collection.Count == 0;
}

This is all fine and will return True if the collection/Array are null or empty.
But hey, what about some other, non "ICollection" objects that implements IEnumerable like XmlNodeList?
For that purpose, we can't use the Length or Count properties since we don't have them.
So, let's work with the IEnumerator.
Initially, the enumerator is positioned before the first element in the collection so calling Current will throw an exception. By calling MoveNext we move the enumerator to the first element and the bool value will tell us if it is empty or not. Complicated?
public static bool IsNullOrEmpty(this IEnumerable iEnumerable)
{
    if (iEnumerable != null)
    {
        return !iEnumerable.GetEnumerator().MoveNext();
    }
    return true;
}

Now, since collections and arrays implements IEnumerable we are clear to go.
static void Main(string[] args)
{                        
    List<string> list = new List<string>();
    Console.WriteLine(list.IsNullOrEmpty());//This will print True
    list.Add("Some text");
    Console.WriteLine(list.IsNullOrEmpty());//This will print False
}

But wait, didn't I say "some" extension methods?
Another one I use when I'm writing console applications is:
public static void Print(this Object obj)
{
    Console.WriteLine(obj);
}
I use this trick when I need to change the output target according to configuration or command line input.
The result will look this:
static void Main(string[] args)
{                        
    List<string> list = new List<string>();
    list.IsNullOrEmpty().Print();//This will print True
    list.Add("Some text");
    list.IsNullOrEmpty().Print();//This will print False
}

Thursday, April 23, 2009

Find a key by its value in a NameValueCollection

While I was working one of my samples, I came across a nice problem: "How do I get a key from a NameValueCollection by its value?"
Assume the following declaration:


NameValueCollection nvc = new NameValueCollection { { "a", "abc" }, { "b", "bcd" }, { "c", "cde" } };

Well, I can try to explain why I needed it but I assure you it wasn’t so important. In fact, the only added value of this sample was me finding a nice solution to this problem :)

Back to the point, there was, of course, the strait forward solution of iterating on the list and checking for a match on each value but that was too ugly even for a sample.
So, why not recruit LINQ to the rescue?
A small attempt made me realize that though the collection implement IEnumerable, the enumeration works only on the keys so still no cookies for me.

Couple of more hits on the head with a club made me remembered that I have Extension methods in my arsenal. I know I had previously warned about in this post.
Well, I guess it can now come in handy.


public static class SampleExtensions
{
public static IEnumerable<KeyValuePair<string, string>> GetPairs(this NameValueCollection coll)
{
if (coll == null)
{
throw new ArgumentNullException("throw something here");
}
return coll.Cast<string>().Select(key => new KeyValuePair<string, string>(key, coll[key]));
}
}

Nothing fancy here. The cast was done so I could use the select method.


var result = (from pair in nvc.GetPairs() where (string.Compare( pair.Value,"abc")==0) select pair.Key);

result.ToList<string>().ForEach(str => Console.WriteLine(str));

Now for the usage. The search is now done on a KeyValuePair and now I have access to the value in each pair.
The last line prints the result to the console and there you have it.

Ugh!
I'm sure there was a good reason why this feature was left on the drawing board.

Saturday, February 21, 2009

Respect your extension methods

One of the nice things in C# 3.0 is extension methods. I won't go into details about it but would like to focus on the hazards when actually writing beyond the plain examples.
However, I will use a plain example myself since I don't want you to fall asleep.

Since the method binding is done at compile time, you will get a different behavior depending on the assigned type.

Suppose we have 2 (plain) objects:


public class BaseObject
{ }
public class DerivedObject : BaseObject
{ }

Now for the extension method:


public static class ObjectExtensions
{
public static void ExtensionMethod(this BaseObject obj)
{
Console.WriteLine("In BaseObject extension version");
}
}

The Main method is very simple:


static void Main(string[] args)
{
BaseObject baseObj = new BaseObject();
DerivedObject derObj = new DerivedObject();
baseObj.ExtensionMethod();
derObj.ExtensionMethod();
}

I've declared 2 objects and when I run this sample I get:
In BaseObject extension version
In BaseObject extension version

So far so good; 2 object, 1 extension and 1 expected result for both calls.
Remember the compile time binding thing? Lets add the another version for the extension method. It goes like:


public static void ExtensionMethod(this DerivedObject obj)
{
Console.WriteLine("In DerivedObject extension version");
}

Now, when running this sample again, I get:
In BaseObject extension version
In DerivedObject extension version

"Is he ever going to get to the point?"
Well, the point is this: add these 3 lines to the main method and see what happens.
BaseObject[] arrOfObj = { baseObj, derObj };
arrOfObj[0].ExtensionMethod();
arrOfObj[1].ExtensionMethod();

We are back to BaseExtension for both new calls even though one of them is a derived type.

The danger is obvious. It is very easy to keep your gourds down and write some buggy lines of code that will make you bold trying to figure out what the heck went wrong.
Of course, there are other words of caution in this subject:

When it comes to your extension method versus the original object version, yours will always loose. The extended version will never be called.
"Why the heck would you extend a method that already exists?"
Well, the first option is that it didn't exist at the time and was added to the object at a later point of .net life. You know, great minds think alike.
The second option is that I tried to override the original behavior. No treats for me in both poor scenarios!

"Well, am I at list entitled to access some private fields of the extended object?"
Hmm, no! You see, extension method is just a way to call a static method from the instantiated object.

You will find many great examples on how to do nifty things with extensions.
My advice is to avoid it if you can inherit and add it in the derived object. In case you can't or don't have access to the code then use it with care.