Extension Methods were introduced in VB.NET 2008 primarily to support LINQ - Language Integrated Query. But they open up a whole new dimension of programming possibilities by themselves. This article tells you how to use them.
Here's a definition courtesy of Scott Wisniewski, a developer on the VB 9 Compiler Team:
"Extension methods enable you to create a method in a module decorated with an attribute and have that method appear as if it was an instance method defined on another type."
Huh!? Let's go through that a little slower.
If a method from another class is declared as "Shared" then you can use it in your code without creating an instance. For example:
Public Class mySharedMethod
Shared Sub SharedExample()
MsgBox("This method is shared" _
& "No instantiation required.")
End Sub
End Class
Private Sub Button1_Click( ...
mySharedMethod.SharedExample()
End Sub
Otherwise, you have to create an instance of the class (in other words, an "object") to use the method.
Public Class myNonSharedMethod
Public Sub NonSharedExample()
MsgBox("This method is not shared" _
& "An instance must be created.")
End Sub
End Class
Private Sub Button1_Click( ...
Dim nonShared As New myNonSharedMethod
nonShared.NonSharedExample()
End Sub
Most of the time, this works great. It's only a problem when you need to modify a class that already exists. That's what Scott means by, "have that method appear as if it was an instance method defined on another type." "Type" is one of those words that gets used a lot but isn't really well defined. In general, it's almost the same thing as "object". The "type" of the variable "nonShared" above is "myNonSharedMethod". The "type" of "ABCDE" is String.
You can usually extend an existing class by inheriting it like this:
Private Class myInheritsExample
Inherits myNonSharedMethod
Sub newSub()
MsgBox("From the newSub method")
End Sub
End Class
Methods can be used from the original class and the new class now:
Private Sub Button1_Click( ...
Dim myInherits As New myInheritsExample
myInherits.NonSharedExample()
myInherits.newSub()
End Sub
A class can be "sealed" and then it can't be inherited. In the example we will use, the Char type will be extended. Extension methods give you a way to add your own method to the Char class. For example suppose I decided to create a really simple minded cypher to protect strings from curious eyes consisting of simply subtracting 1 from the ASCII code for any character.
Public Function CharMinusOne(ByVal C As Char) As Char
Dim ascCode As Integer = Asc(C)
If ascCode = 0 Then ascCode = 255 _
Else ascCode -= 1
Return Chr(ascCode)
End Function
I can add this function to the .NET String class using extension methods. As Scott states, we first have to "create a method in a module decorated with an attribute". Note the limitation, "in a module" however. Because I wanted to clearly show what Shared and non-Shared methods were, I used a class in my code above. But extension methods can only be coded in modules. Since modules can't be instantiated (only classes can), you don't have to use the "Shared" keyword.
You might be unfamiliar with the term "decorated". As Scott uses the term here, it simply means that an "attribute" has been added to the code. Extension methods require a very specific one:
<System.Runtime.CompilerServices.Extension()>
The namespace "System.Runtime.CompilerServices" is often named in an Imports statement so only "<Extension()>" is needed.
With these details, here's the complete code for our extension method:
Namespace AVBStringNS
Public Module AVBStringModule
<System.Runtime.CompilerServices.Extension()> _
Public Function CharMinusOne(ByVal C As Char) As Char
Dim ascCode As Integer = Asc(C)
If ascCode = 0 Then ascCode = 255 _
Else ascCode -= 1
Return Chr(ascCode)
End Function
End Module
End Namespace
The "Namespace" isn't strictly required, but it helps to guarantee that your extension method isn't confused with anything else. The Visual Basic team recommends the use of a namespace. If a name conflict occurs - and it's very possible because you often have no idea what else is in the class that you're modifying - the namespace identifies your new method. Remember that if the class you're modifying already has a method with the same name, the one in the class will always be used. As the Visual Basic team puts it in their blog, "any accessible instance member on a type will always shadow any extension methods with the same name."
The actual syntax of the extension itself only has one important rule: The type of the first parameter is the data type that is being extended. The first parameter of the extension above - CharMinusOne - is of type Char - "ByVal C As Char" - so that's the type being extended here.
The hard part is (well ... mostly) over now because consuming extensions is simple. One of the real achievements of the Visual Basic developers was to make extensions fully incorporated into Intellisense just as soon as they're coded and in scope for the consuming code. That means that if the AVBStringNS is in scope, all we have to do is start coding ...
--------
Click Here to display the illustration
Click the Back button on your browser to return
--------
On the next page, I put this extension to use.

