Microsoft & .NETVisual BasicImplementing Extension Methods in VB.NET

Implementing Extension Methods in VB.NET

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

I wrote my first VB code in 1978. I am not surprised that programming is still fun, still interesting, still amusing after all these years. Computers really got interesting for the average person around 1986, ten years after Bill Gates started Microsoft, but just two years after Microsoft went public. It’s a little sad that Chairman Bill is retiring already.

The good news is that with Vista and .NET 3.5, Microsoft is putting out some their best products and tools ever. A significant amount of my time will be spent on an SAP implementation for several months, but I am stealing time for Orcas—it’s just too much fun. And, my employer and boss, in their infinite wisdom, are sending a delegation of us to Orlando for TechEd 2007. I hope to see you there.

In this article, I am introducing Extension Methods. Extensions Methods are an implementation of the Composite Structural design pattern. Extension methods permit you to add behavior to a class without creating a wrapper. The result is that the extension method looks like any other member of a class. For example, you can add additional behaviors to something like strings without inheriting from the String class. The benefit is that the new behavior looks like any other member from the code’s point of view, and it doesn’t introduce subclasses that could potentially introduce breaking changes.

Extension methods are something you will want to learn and they are useful for Microsoft’s Language Integrated Query (LINQ). In this article, I created an extension to String that uses the Speech library, so you get a little two for one action.

Implementing an Extension Method

An extension method is simply a shared method adorned with the ExtensionAttribute. The ExtensionAttribute is a compile-time cue that tells the compiler to resolve calls to a method in MSIL. For example, if you define an extension method, Speak, that accepts a String argument, you can call the extension method as if it were a member of the String class. (In case you don’t know it yet, everything is a class in .NET even though variables like strings look like native types.)

Listing 1 shows a stub of an Extension Method named Speak followed by code that demonstrates how you would call Speak.

Listing 1: Defining an extension method is as easy as tagging the method with the System.Runtime.CompilerServices.ExtensionAttribute class.

<System.Runtime.CompilerServices.Extension()> _
Public Sub Speak(ByVal s As String)

End Sub

To invoke the method, declare a string variable and use normal method invocation syntax:

Dim s as String = "Hello, World!"

s.Speak()

Listing 2 contains a complete, simple application that was a prank on my kids. To create the project, download .NET 3.5 Beta 1 and add a reference to System.Speech.dll. You kind find this DLL in the 3.5 framework folder by using Explorer’s search capability.

Listing 2: By using an extension method and the speech capabilities of .NET, you can make the Strings talk.

Imports System.Speech.Synthesis
Imports System.Runtime.CompilerServices


Module Module1

   Sub Main()

      Dim s1 As String = "Is anyone out there"
      Dim s2 As String = "help"
      Dim s3 As String = "we are stuck in here"
      Dim s4 As String = "yes"
      Dim s5 As String = "help us"

      While (True)

         s1.Speak()

         System.Threading.Thread.Sleep(1000)
         s2.Speak()
         System.Threading.Thread.Sleep(1000)
         s3.Speak()


         If (rnd.Next(1, 7) Mod 3 = 0)Then
            System.Threading.Thread.Sleep(500)
            s4.Speak()
            System.Threading.Thread.Sleep(200)
            s5.Speak()
         End If

         System.Threading.Thread.Sleep(500)
      End While

   End Sub


   Private rnd As Random = New Random

   <System.Runtime.CompilerServices.Extension()> _
   Public Sub Speak(ByVal s As String)

      Using synth = New SpeechSynthesizer

         If (s = "yes" Or s = "help us") Then
            synth.SelectVoice(synth.GetInstalledVoices() _
               (rnd.Next(0, 2)).VoiceInfo.Name)
         End If

         synth.SelectVoice("LH Michelle")

         synth.Speak(s)

      End Using
   End Sub
End Module

The code in bold—the Speak method—defines the Speak extension method. All you have to do is add the ExtensionAttribute to define an extension method. Making your computer talk is as easy as creating an instance of the SpeechSynthesizer class.

Compiling .NET 3.5 Beta 1 Code

If you try to compile the code in Visual Studio 2005, you will get a compiler error for the call String.Speak. You will need to use the .NET 3.5 VBC compiler. You can compile the module easily with a command line statement that invokes the correct compiler and adds library references. Here is the command line I used.

C:WINDOWSMicrosoft.NETFrameworkv3.5.20404vbc module1.vb/out:sp.exe
/reference:Microsoft.VisualBasic.dll /reference:"C:Program Files
Reference AssembliesMicrosoftFrameworkv3.0System.Speech.dll"
/libpath:"C:WINDOWSMicrosoft.NETFrameworkv3.5.20404

Make sure you add a reference to the Microsoft.VisualBasic.dll, the System.Speech.dll, and set the library path to point to the .NET 3.5 framework. The output is sp.exe. You can name it anything you’d like.

At the present time, you can only use modules and functions for extension methods. In C#, you can put extension methods in their own classes. Because Modules are really just classes with all shared members, I’d like to see Microsoft change Extension behavior for VB to support putting extension methods in their own classes.

Summary

Extension methods are already used a lot of places in the upcoming versions of .NET. For instance, they make the yield return pair work with iterators. You can easily create extension methods by defining a method in a module and adding the ExtensionAttribute to functions. Because modules are really classes, there is no problem adding modules anytime you need an extension class.

If you are interested in the plumbing, get a copy of Lutz Roeder’s Reflector to look at the MSIL. It is probably reasonable to see some evolution in grow Extension methods work, like class support and perhaps property support. Check out Scott Guthrie’s blog to stay up to date on new .NET features.

Finally, before Chairman Bill retires, I’d like to invite him to speak at our user group, glugnet.org, and I’d like to thank the always entertaining Martin Shoemaker for presenting his cool toy DeeJay and Microsoft’s improved Speech capabilities for Vista. (Sorry about the clacking keyboard Thursday; I had a deadline.)

About the Author

Paul Kimmel is the VB Today columnist for www.codeguru.com and has written several books on object-oriented programming and .NET. Check out his new book, UML DeMystified, from McGraw-Hill/Osborne. Paul is an architect for Tri-State Hospital Supply Corporation. You may contact him for technology questions at pkimmel@softconcepts.com.

If you are interested in joining or sponsoring a .NET Users Group, check out www.glugnet.org.

Copyright © 2007 by Paul T. Kimmel. All Rights Reserved.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories