Extension methods are a new language feature in C# and VB.NET which in essence is one of the underpinnings of the new LINQ (Language INtegrated Query) syntax new to .NET.
At first look, extension methods seem to “add” functionality to existing types. But in reality they simply allow you the flexibility of making static method calls more intuitive within the framework of your code by allowing you to attach those methods to existing types (which you may or may not have the source-code to).
As an example, I’ve taken a common task that I find myself doing in my code quite a bit. Having a generic List(Of T) of business objects, I want to find the one object in that list that has a particular ID.
27 Public Shared Function GetByID(Of T As PersistLoad)(ByVal a_List As List(Of T), ByVal a_ID As Integer) As T
28 Dim current As T = Nothing
29 For Each obj As T In a_List
30 If obj.ID = a_ID Then
31 current = obj
32 Exit For
33 End If
36 Return current
37 End Function
Using this generic implementation, I can pass in any list of objects, the ID I want to search for, and either return an object of type T or nothing/null. This works fine, however if I want to do the same for another data type, e.g. like a Dictionary, I have to write a new method that knows how to iterate over that type of object.
The calling code for this implementation would be something like:
112 m_CurrentBarcode = ExtensionsRegular.GetByID(m_Barcodes, a_BarcodeID)
Notice that I have to pass in as an input parameter the actual list of objects (in this case, barcodes)? Additionally, the method is simply called from a static/shared method repository class called ExtensionsRegular.
Now, let’s look at how an extension method can help us here.
7 <Extension()> _
8 Public Function FindByID(Of T As PersistLoad)(ByVal list As IEnumerable(Of T), ByVal a_ID As Integer) As T
9 Dim selected = _
10 From b In list _
11 Where b.ID = a_ID _
12 Select b
14 If selected.Count > 0 Then
15 Return selected.First()
17 Return Nothing
18 End If
19 End Function
Notice with the extension method implementation, we can use the IEnumerable generic interface as the input. We’ll come back to why that’s important in a minute. Inside the implementation of the extension method, we are using a LINQ query that selects from the list (which must implement IEnumerable or it’s generic equivalent IEnumerable) where the ID equals the a_ID parameter we passed in. Notice 1) how similar this is to SQL queries and 2) how natural it looks to the reader in terms of what is actually being done in the code.
Now our calling code looks like:
114 m_CurrentBarcode = m_Barcodes.FindByID(a_BarcodeID)
Because it’s an extension method, the compiler actually allows the method to be called as if it were an instance member method. Notice that the only input parameter is the ID we’re searching for.
Additionally, since we used the IEnumerable(Of T) interface as our input declaration, we can now use this exact same extension method if we were trying to FindByID on basically ANY type (in the .NET framework or otherwise) which implements IEnumerable(Of T), since any IEnumerable type must implement the MoveNext() method.