Partial Methods

VBTeam

About two weeks ago I had the opportunity to attend the product group dinner associated with the Global MVP Summit that was behind held here at Microsoft. Besides a free meal, this also gave me the excellent opportunity to meet with some of our MVPs and discuss their impressions with Visual Studio and all the cool new features we are introducing for Orcas. At the dinner, I had an opportunity to talk with a group of VB MVPS from Japan, who met with me and about 5 or 6 other members of the VB team. While we were talking, a couple of them asked me a few questions about partial methods. Unfortunately, I do not speak Japanese, and so had some trouble answering them. Figuring that written English may be easier to understand than my idiomatic spoken English, I decided to make Partial Methods the topic of my next blog post.

As a result, I’ve included their questions below along with my answers.

What are Partial Methods?

In a nut-shell, partial methods are a light-weight replacement for events designed primarily for use by automatic code generators. They are declared by creating a private method with an empty body and decorating it with the Partial keyword. The method may then be “re-implemented” elsewhere within its containing class. If the method is implemented, then the compiler will redirect all calls to the partial method to the implementing method. If the method is not implemented in its containing class, then the compiler silently removes any calls to it from the program. They differ from events in several ways, mainly:

  1. A partial method can only have 1 “implementing method”, where events may have any number of handlers
  2. The implementing method for a partial method must be in the same class as the partial method its self, where as event handlers can pretty much be defined in any type that has access to the event instance
  3. An event will throw if it has no handlers and is invoked. Usually this requires comparing the event against Nothing to safe guard against an exception. On the other hand, if a partial method does not have an implementing method then the compiler will simply optimize away any calls to it.
  4. The wiring of events is dynamic, which means that handlers can be added and removed from an event at runtime. This can either be done implicitly, using WithEvents variables and Handles clauses or explicitly using AddHandler and RemoveHandler statements. The wiring of partial methods, however, is always done at compile time, and an implementing method is associated with its declaring method by simply writing a method with the same name and signature as the partial method. Once this is done, all references to the partial method are rewritten by the compiler to refer to its implementing method.
  5. Events may be declared with any accessibility (public, private, or friend). Partial Methods, on the other hand must be private. The method that implements it, however, may have any accessibility.

An example use of partial methods is shown below:

‘Designer File
Partial Class DesignerGeneratedClass
   
Partial Private Sub OnFoo() 
    
End Sub

    Partial Private Sub OnBar()
   
End Sub

    Sub DoSomething()
       
OnFoo()
       
OnBar()
   
End Sub
End Class

‘Code Behind File
Class DesignerGeneratedClass
   
Public Overridable Sub OnFoo()
       
Console.WriteLine(“Foo Occured”)
   
End Sub
End Class

Here we define a class named DesignerGeneratedClass split into two partial classes. It is designed to mimic typical code generation scenarios where one partial class contains designer generated code and another contains user generated code. For example, Windows Forms classes and pages in ASP.NET Web Application Projects utilize this approach. In the designer generated file we define a utility method, DoSomething, that calls two partial method declarations OnFoo and OnBar. The user file implements OnFoo, but not OnBar. When the VB compiler processes this class, it notices this and emits a body for DoSomething() that only calls OnFoo().

What are Partial Methods useful for?

For most applications, events are almost always a better choice than partial methods due to their increased flexibility. However, there are some scenarios where they come in handy. A couple of them are listed below:

  1. In automatic code generators

    Partial methods enable code generators to write extremely flexible code by creating a lot of “hooks”, where developers can provide their own custom functionality that integrates into the “boiler plate” code created by the generator. Because the hooks are optimized away if they aren’t used, no performance penalty is introduced by defining them. This is really useful if generated code needs to be used in high performance scenarios. For example, partial methods are used by the DLINQ designer for exactly this purpose. Developers wishing to invoke custom code on their data objects when properties are set can do so without requiring all users of DLINQ to suffer performance problems.

  2. To increase the readability of code that uses conditional compilation constants.

    Consider the following code that uses conditional compilation constants in VB.

    Class
    UglyConditonalCompilationCode

    #If DEBUG Then
        Private Sub LogMessage(ByVal s As String)
            Console.WriteLine(s)
        End Sub
    #End If

        Sub DoStuff()
            DoFirstThing()
    #If DEBUG Then
            LogMessage(“Did first thing”)
    #End If
            DoSecondThing()
    #If DEBUG Then
            LogMessage(“Did second thing”)
    #End If
            DoThirdThing()
    #If DEBUG Then
            LogMessage(“Did third thing”)
    #End If
        End
    Sub
    End
    Class

    This code is obviously difficult to read. However, using partial methods it is possible to make the code much more readable:

    Class PrettyConditonalCompilationCode
        Partial Private Sub LogMessage(ByVal s As String)
        End Sub

    #If DEBUG Then
        Private Sub LogMessage(ByVal s As String)
            Console.WriteLine(s)
        End Sub
    #End If

        Sub DoStuff()
            DoFirstThing()
            LogMessage(“Did first thing”)
            DoSecondThing()
            LogMessage(“Did second thing”)
            DoThirdThing()
            LogMessage(“Did third thing”)
        End Sub
    End
    Class

Are Partial Methods Some Form Of AOP (Aspect Oriented Programming)?

No. Partial methods do share some things in common with Aspect Oriented Programming in that partial methods offer a way of associating “hooks” with custom code. However, unlike AOP systems partial methods require extension points to be explicitly defined by the customer. AOP systems allow developers to “weave in” functionality into code that hasn’t had explicit hooks defined. Usually they do this by specifying some declarative search strings that describes the places where the hooks should be applied. The compiler is then responsible for finding all the appropriate “extension points” to apply the hooks to and injecting any necessary method calls. Partial methods in VB do not do this.

0 comments

Leave a comment

Feedback usabilla icon