Partial Method

Partial methods are a C# 3.0 technique used by code generators such as the one found in the LINQ to SQL Designer. A partial class or struct may contain a partial method. One part of the class contains the signature of the method. An optional implementation may be defined in the same part or another part. If the implementation is not supplied, then the method and all calls to the method are removed at compile time.

Partial methods enable the developer of one part of a class to define a method, similar to an event. The developer of the other part of the class can decide whether to implement the method or not. If the method is not implemented, then the compiler removes the method signature and all calls to the method. Therefore, any code in the partial class can freely use a partial method, even if the implementation is not supplied. No compile-time or run-time errors will result if the method is called but not implemented.

Partial methods are methods that enable lightweight event handling. Likely we already know about partial classes, which were added in the 2.0 timeframe. Partial classes allow us to split the definition of a class across multiple files, or alternatively we could think about it as a code compilation unit separated over multiple files. The reason for the existence of this feature is - primarily - to provide a nice split between generated code and user code, as in the Windows Forms Designer that generates its code in a separate file, while developers have almost full control over the form's other code file .

When combined with partial classes, partial methods allow the developers of auto-generated code to reserve a name for a method that can be optionally implemented by the consumer of the class. This gives a developer a place where she can optionally add code that will never be overwritten if the code generation tool is re-run.

using System;

namespace PartialMethods
{
    // Assume this is a autogenerated class
    public partial class MyAutoGenClass
    {
        partial void MyPartialMethod();

        public void CallPartialMethod()
        {
            MyPartialMethod();
        }
    }

    // Assume this  is explicitly written class
    public partial class MyAutoGenClass
    {
        partial void MyPartialMethod()
        {
            Console.WriteLine("Second half");
        }
    }

    class Example
    {
        static void Main(string[] args)
        {
            MyAutoGenClass p = new MyAutoGenClass();
            p.CallPartialMethod();
        }
    }
}

Assume that the first instance of MyAutoGenClass was auto-generated by a visual designer that is part of Visual Studio. Notice that the class is declared as partial, as is MyPartialMethod. Notice that MyPartialMethod contains a header (or call as just declaration), but no implementation. You can consider this an invitation to the developer to implement this method if desired.

Assume that the developer took up the invitation and created by hand the second half of MyAutoGenClass. In this class he has written his implementation for MyPartialMethod, which will duly be called at runtime by the code in the first part of this partial class. If he had decided to decline the invitation, then the code to call MyPartialMethod would have been optimized out by the compiler, causing all traces of MyPartialMethod to be entirely eliminated at run time.

This system allows the developer to re-run the designer that created the first part of MyAutoGenClass without fear that this action would overwrite the code in her half of MyAutoGenClass. It also allows the developer to work with a relatively small implementation of MyAutoGenClass that contains only a few methods, without needing to wrestle with the potentially long and complex listings that are often found in auto-generated code.

Ofcourse , we need to prove this. Here we go.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PartialMethod
{
  using System;

  partial class PartialMethods //Part 1
  {
    static void Main()
    {
      Do();
    }

    static partial void Do();
  }

  partial class PartialMethods //Part 2
  {
    static partial void Do() { }
  }

}

Here we have defined both parts of the partial class in the same file, but in real scenarios you'd have the two parts in separate files of course. In part 1 of the class definition, We have declared the Do method as partial. Notice it's a static but that doesn't need to be the case, it works in a similar fashion with instance methods. Partial methods don't take an implementation body, it's just a declaration, much as we are used to in interfaces or abstract classes. In part 2 of the class definition, We have implemented the partial method, for demo purposes just with an empty body.

In reality, the complete definition from above is equal to:

using System; 

class PartialMethods
{
   static void Main()
   {
      Do(); 
   } 

   static void Do() {}
}

If you take a look at the IL code, we can see that the Main method contains a call to the Do method.



Re-complie the code as below. We have removed the defintion of the partial method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PartialMethod
{
  using System;

  partial class PartialMethods //Part 1
  {
    static void Main()
    {
      Do();
    }

    static partial void Do();
  }

  partial class PartialMethods //Part 2
  {
//    static partial void Do() { }
  }

}

Even though there is the Do() method call in the Main() method, we cannot see that call in the IL code, because the partial method Do() is not defined.Right, no single trace of Do at the caller's side. It goes even further than that: all of the parameters evaluation is omitted too.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PartialMethod
{
  using System;

  partial class PartialMethods //Part 1
  {
    static void Main()
    {
      int i = 0;
      Console.WriteLine(i);
      Do(i++);
      Console.WriteLine(i);

    }

    static partial void Do(int i);
  }

  partial class PartialMethods //Part 2
  {
    static partial void Do(int i) { }
  }

}



Code by omitting the partial method defintion.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PartialMethod
{
  using System;

  partial class PartialMethods //Part 1
  {
    static void Main()
    {
      int i = 0;
      Console.WriteLine(i);
      Do(i++);
      Console.WriteLine(i);

    }

    static partial void Do(int i);
  }

  partial class PartialMethods //Part 2
  {
    //static partial void Do(int i) { }
  }

}



In this sense, partial methods are the distant cousins of conditional methods which also sometimes remove the call and the evaluation of the arguments. But partial methods go even further. When a partial method has no body then the partial method is not even emitted to metadata.

Why Partial Methods?

So how are these partial methods used? The common scenario is to use them to do lightweight event handling. For example a tool that generates code may wish to have hooks for users to customize what code is run. For example, imagine that a tool generated a bunch of code for a class representing a customer. It might look like this:

partial class Customer
{
  string name; 

  public string Name
  {
    get
    {
      return name;
    }
    set
    {
      OnBeforeUpdateName();
      OnUpdateName();
      name = value;
      OnAfterUpdateName();
    }
  } 

  partial void OnBeforeUpdateName();
  partial void OnAfterUpdateName();
  partial void OnUpdateName();
}

If the user doesn't add any implementing definitions then this code is equivalent to:

partial class Customer
{
  string name; 

  public string Name
  {
    get
    {
      return name;
    }
    set
    {
      name = value;
    }
  } 

}

No extra metadata for things that are not used and no extra instructions for useless operations. On the other hand if the user listened to the OnUpdateName "event" like this:

partial class Customer
{
  partial void OnUpdateName()
  {
    DoSomething();
  }
}

Then the original definition is equivalent to:

partial class Customer
{
  string name; 

  public string Name
  {
    get
    {
      return name;
    }
    set
    {
      OnUpdateName();
      name = value;
    }
  } 

  partial void OnUpdateName();
}

The rules governing partial methods state that they:

  • Partial methods must be declared within partial classes
  • Partial methods are indicated by the partial modifier
  • Partial methods do not always have a body
  • Partial methods must return void
  • Partial methods can be static
  • Partial methods cannot be marked as extern
  • Partial methods can be marked static or unsafe
  • Partial methods can be generic
  • Partial methods can have ref parameters, but not out parameters
  • Partial methods cannot be referenced as a delegate until they are implemented
  • Partial methods cannot have access modifiers such as public, private or internal. Partial methods are implicitly marked as private. This means they cannot be called from outside the partial class, and cannot be declared as virtual

At this point, it is sensible to ask why not just use subclassing and virtual methods? Of course, this would also work but it does have the drawback that the calls, the methods, and the evaluation of the arguments will still be emitted even if the virtual methods are not overridden. So in a system like Linq to SQL that has thousands of little events it allows these events to be very lightweight so that the user only pays for those events that she uses.

Reference Articles