During my time working, I find that developers can get lazy and start using the COPY and PASTE commands to a degree that can make code unmanageable.
There are many things we can do to reduce, if not eliminate, the code management nightmare, however, the one way I will focus on is using extension methods.
So what are extension methods ? and why should we use extension methods ? Let’s try to answer these questions in a scenario.
Let us assume we have a type, and this type is called “Int”, in our application we use our Int types A LOT.
We find that we either keep re-coding certain snippets of code or just lazily applying the copy, paste and replace procedure in order to complete or patch our application.
Now what happens when that logic has a bug or needs to be changed ? would you go to each implementation and fix it ? wouldn’t life be easier if this piece of logic could be changed in just one place ?
I’m not saying the using extension methods is the ONLY approach, but it is the approach we will be going through.
Here are a few rules before we go on to the code:
- your extension classes should be public and static
- your extension methods should be public and static
Let’s assume we had an array of integers:
int[] numbers = new int[]
{
1, 3, 5, 6, 8, 9, 10
};
We needed to loop through this list of integers and determine if each number is even or odd, additionally we needed to determine if each number is a prime number or not.
Lets attempt to code this without using extension methods (the not so manageable approach).
int[] numbers = new int[]
{
1, 3, 5, 6, 8, 9, 10
};
foreach(int i in numbers)
{
Console.WriteLine(i.ToString());
bool isEven = ((i % 2) == 0);
if(isEven)
{
Console.WriteLine("\tEven");
}
else
{
Console.WriteLine("\tOdd");
}
if(i == 1)
{
Console.WriteLine("\tNot Prime");
} else if (i == 2)
{
Console.WriteLine("\tIs Prime");
}
else
{
bool isPrime = true;
double boundry = Math.Floor(Math.Sqrt(i));
for (int j = 2; j <= boundry; ++j)
{
if ((i % j) == 0)
{
Console.WriteLine("\tNot Prime");
isPrime = false;
break;
}
}
if(isPrime)
{
Console.WriteLine("\tIs Prime");
}
}
}
notice how long and messy this code looks ? using extension methods we can make this code more elegant and managable.
lets start of by creating a new class file and we can call this “SimpleExtenionMethods.cs”
this class should contain the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExtensionMethodSample
{
public static class SimpleExtensionMethods
{
public static bool IsEven(this int i)
{
return ((i % 2) == 0);
}
public static bool IsPrimeNumber(this int i)
{
if (i == 1) return false;
if (i == 2) return true;
double boundry = Math.Floor(Math.Sqrt(i));
for(int j = 2; j <= boundry; ++j)
{
if ((i % j) == 0) return false;
}
return true;
}
}
}
and here’s the implementation
// number array
int[] numbers = new int[]
{
1, 3, 5, 6, 8, 9, 10
};
// out each result
foreach(int i in numbers)
{
Console.Write("Testing #" + i.ToString() + ":\t");
if(i.IsEven())
{
Console.Write("Evem");
}
else
{
Console.Write("Odd");
}
if(i.IsPrimeNumber())
{
Console.Write( ", Prime Number");
}
Console.WriteLine();
}
is that not so much simpler, elegent and far more readable ?
here’s the result:
Testing #1: Odd Testing #3: Odd, Prime Number Testing #5: Odd, Prime Number Testing #6: Even Testing #8: Even Testing #9: Odd Testing #10: Even
lets take this step further, what if we wanted to split the ODD and EVEN numbers into seperate list objects ?
lets create a new class file called “SlightlyComplexExtensions.cs”
the code should be as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExtensionMethodSample
{
public static class SlightlyComplexExtensions
{
public static Dictionary<string, List<int>> SplitNumbersIntoSections(this int[] iArr)
{
Dictionary<string, List<int>> result = new Dictionary<string, List<int>>();
result.Add("Odd", new List<int>());
result.Add("Even", new List<int>());
foreach(int i in iArr)
{
if(i.IsEven())
{
result["Even"].Add(i);
}
else
{
result["Odd"].Add(i);
}
}
return result;
}
}
}
and here’s the implementation:
// number array
int[] numbers = new int[]
{
1, 3, 5, 6, 8, 9, 10
};
// split array into sections
Dictionary<string, List<int>> numberSplit = numbers.SplitNumbersIntoSections();
// out each section
foreach(string key in numberSplit.Keys)
{
// key will either be EVEN or ODD
Console.WriteLine(key + ":");
// out the numbers in the section
foreach(int i in numberSplit[key])
{
Console.WriteLine("\t" + i.ToString());
}
}
here’s the result:
Odd:
1
3
5
9
Even:
6
8
10
Let us now take this one more step further, we now wish to generate a third list containing the prime numbers, this can be done without changing the implementation code. All that changes is the extension method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExtensionMethodSample
{
public static class SlightlyComplexExtensions
{
public static Dictionary<string, List<int>> SplitNumbersIntoSections(this int[] iArr)
{
Dictionary<string, List<int>> result = new Dictionary<string, List<int>>();
result.Add("Odd", new List<int>());
result.Add("Even", new List<int>());
result.Add("Prime", new List<int>());
foreach(int i in iArr)
{
if(i.IsEven())
{
result["Even"].Add(i);
}
else
{
result["Odd"].Add(i);
}
if(i.IsPrimeNumber())
{
result["Prime"].Add(i);
}
}
return result;
}
}
}
here’s the result:
Odd:
1
3
5
9
Even:
6
8
10
Prime:
3
5