Extension methods (part 1)

Extension methods (part 1)

Rate This
  • Comments 21

Hi.

I'm Scott Wisniewski, a dev on the VB Compiler Team. I've been here for a while now (about a year and a half), but this is my first blog post. I've been spending the past seven months or so working on Orcas, and finally decided it would be a good time to come up for some air, talk about what I've been working on, and start to actually make a dent against my blogging commitments.

I figured the best place to start is with my favorite feature: extension methods. If you didn't know this already, one of the new features we are adding to VB 9.0 is Extension Methods, which provide a very powerful and elegant way to inject your own custom functionality into other people's types. In particular, through a great deal of compiler magic, 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. Here is a simple example, where we define an extension method that adds a method called "Speak" directly to the string class.

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

Module Module1
   
<Extension()> _
   
Sub Speak(ByVal x As String)
       
Using synth As New SpeechSynthesizer()
           
synth.Speak(x)
       
End Using 
    
End Sub

   
Sub Main()
       
Dim x = "Hello World"
       
x.Speak()
   
End Sub
End Module

This method then wraps up the speech API, causing the string to be spoken through the computer's speakers.

If we examine the method definition, it looks more or less exactly like any run-of-the-mill helper routine, with the notable exception of it being decorated with the "System.Runtime.CompilerServices.Extension" attribute. The use of this attribute instructs the compiler to treat the method as an extension method, which in turn causes the new helper method to appear as if it was a pre-defined instance method automatically available to users of the string class.

If we compare this to the old way of doing things, the feature really starts to show its elegance. In Whidbey, helper routines that operated on common types(particularly non-extensible types like "string", "sealed classes", and interfaces) often suffered from a few draw backs. Mainly:

  1. They were not easily discoverable through intellisence
  2. They use an awkward, counter-intuitive syntax

Intellisence is, in my opinion, one of the greatest programming tools ever invented. Beyond the obvious productivity gains it introduces, is the tremendous discoverability it provides. Many programmers (myself included) often find themselves dealing with objects they have either never seen before or are generally unfamiliar with. In these cases, Intellisence proves to be incredibly valuable, because it allows you to effortlessly discover how these objects work. If you want to know what data is stored in an object, or what operations it is capable of performing, you simply just need to type a "." after the object name or the operation that provided the object to you and intellisence will sweep in and provide you a nice organized picture of what the object is capable of.

With custom-written shared utility methods in Whidbey, however, this kind of discoverability is not possible. Although intellisence will provide parameter info about how to call these methods, and will provide code completion if you start to type their names, it provides little in the way of help for people who do not know that these utility methods exist and are available for their consumption. In particular, calling a utility method uses a different syntax than calling an instance method (Speak("Hello World") versus "Hello World".Split()), and so while typing "." after a string will display "Split" amongst the list of possible choices, and parameter info will be provided after typing "Speak(", the user of an API has to know, ahead of time, weather the function he or she is calling is a shared utility method written by a third party or an instance method provided directly by the class author in order to get help from the compiler about how to use it.

Extension methods in Orcas, however, fix this problem by merging third party utility methods with canned instance methods written by class authors, essentially making utility methods just as discoverable as the built-in ones. The screen-shot below shows an example of this in action:

Extension Methods Are Cool

A programmer in Whidbey, who may not have been aware that a helper method named "Speak" existed, would receive immediate feedback in Orcas about its existence. Personally, I think this is revolutionary.

Also, instance methods have a distinct advantage over shared utility methods in that they make it much easier to chain operations together. As an example, consider a task which requires Translating a string from English to Spanish, running it through a grammar checker, and then finally sending it out as the body of an Email message. Accomplishing this using helper methods may look something like this:

SendEmailToCustomer(TranslateToSpanish(RunGrammerChecker("Extension methods are cool".) ) )

This has the problem, however, of being somewhat counterintuitive. The operations are specified in the opposite order in which they are executed, which makes the code both harder to write and more difficult to understand. If these helper methods were written as Extension methods, however, they could be called just like instance methods allowing users of the API to write something like this:

"Extension methods are Cool".RunGrammarChecker().TranslateToSpanish().EmailToCustomer()

This is easier to write, because intellisence provides better completion lists, and easier to read because the operations are specified in the same order they execute.

In any case, I hope this is enough to wet your appetite for the coolness of extension methods. In my next post, I'll dig a bit more into the details of how they work, the rules for defining them, and how they are used.

Leave a Comment
  • Please add 8 and 8 and type the answer here:
  • Post
  • But this will only cover extension methods that are already pulled into scope, right?  It would be helpful to be able to discover extension methods whose namespaces haven't been imported.  This would be similar behavior to the rather-useful feature that discovers namespaces for types and offers to import or prepend them.

  • "It would be helpful to be able to discover extension methods whose namespaces haven't been imported."  

    That would clutter up intellisense.  I don't want to be bothered with details about a namespace i didn't import.

  • If you are interested in the future of VB, or .NET in general because this is equally true for C#, you

  • I was just reading Rocky's blog entry and thought I'd clarify something Rocky said : Running a LINQ query

  • Nice to hear from you again Scott!! Nate

  • In my previous post I gave a high level overview of some of the benefits of using Extension Methods in

  • kfarmer,

    Thanks for the feature idea. I can't guarantee that we will be able to include your feature in Orcas, but I will forward your request over to the UI team for consieration in a future version of the product.

    One things to consider is that although extension methods are only visible if they are in scope, if you define an extension method in a module in the top level namespace of your of your project (or solution), then you can use these extension methods without having to explictly import them in every file in your project. This won't help with discoverability of extension methods written by third party class library authors, but it will help with extension methods that you or other people on your projects write.

    -Scott

  • Will it be ever possible to replace not-virtual private and protected methods/properties in compiled assemblies? Thanks.

  • In my previous 2 posts I talked about some of the benefits of extension methods and then delved into

  • Hex,

    Thank you for your suggestion. At the momenet we have no plans to support allowing extension methods to override eixsting instance methods. In fact the feature is specifically designed to not allow extension methods to replace the definition of instance methods (instance methods hide extension methods by name, so an extension mehtod can never be called if an instance method with the same name exists on the class). Hower, I will forward your suggestion over to our langauge design team so that they can consider it for a future version of the product.

    Thanks,

    -Scott

  • Here is a list of links to posts on this blog that talk about extension methods: Extension Methods Part

  • L'avvento di .NET 3.5 porterà ai linguaggi che usiamo di più (C# e VB) una serie di novità che sono principalmente

  • Extension methods are a feature of the new C# language specification (also available in Visual Basic

  • Extension methods are a feature of the new C# language specification (also available in Visual Basic

  • Métodos de extensão são uma nova funcionalidade da especificação da linguagem C# (também disponível no

Page 1 of 2 (21 items) 12