Thursday, May 29, 2008 4:14 PM
I get a bit sick of checking for null on my IEnumerable objects before doing a foreach over them. In my opinion I think the CLR should check if the list is null, and if it is just exit out of the foreach iteration as if there were no items in it.
Well, I was goofing around with Extension Methods a bit and figured out how to get this kind of functionality (sort of).
Now unfortunatly Extension Methods cant override an existing method on a type, so I cant just create a new GetEnumerator extension method (well, actually i can make one, but it wont get called). But I can create a new method that returns IEnumerable, and just call the foreach on it.
So in order to do this, first add this class to your code
public static class MyExtnesionMethods
{
public static IEnumerable<T> Enum<T>(this IEnumerable<T> input)
{
if (input != null)
{
foreach (var t in input)
{
yield return t;
}
}
else
{
yield break;
}
}
}
Now, anything that inherits from IEnumerable<T> will have the Enum method. Then all you have to do is call foreach on someClass.Enum(), even if someClass is null. Below is an example of ho this works.
static void Main(string[] args)
{
List<string> names = new List<string>()
{"john", "kim", "jean", "brent"};
//iterate names using stock enumerator
foreach (string name in names)
Console.WriteLine(name);
//iterate names using extension method
foreach (string name in names.Enum())
Console.WriteLine(name);
names = null;
//oh man! I have to check for null...I hate that
if (names != null)
foreach (string name in names)
Console.WriteLine(name);
//Yea! I dont have to check for null anymore!
foreach (string name in names.Enum())
Console.WriteLine(name);
}
The extension method uses the "yield return" and "yield break" iterator syntax to let the foreach either spin over the IEnumerable if its not null, or if it is null, "yield break" returns false from the IEnumerable.MoveNext which tells the foreach that there are no more items in the list so it should break out of the loop.
So, no more null checks!
<Update>
A reader commented that this could be optimized by using the static method Enumerable.Empty<T>. This would save an object instance from being created by the yield return functionality. The new and improved Extension Method is as follows:
public static IEnumerable<T> Enum<T>(this IEnumerable<T> input)
{
return input ?? Enumerable.Empty<T>();
}