Поделиться через


Multimethods in C# revisited

So I thought long and hard about my initial stab at a multimethod implementation for C#. It was a reasonable proof of concept. However, I read some more on the subject of multiple dispatch and the visitor pattern and came up with a few additional ideas. These are encapsulated in the attached project. I have also reproduced the main source file since this is where most of the action takes place.

This was, for me, an interesting digression into the area of IL generation using System.Reflection.Emit which is something I haven't done since my old Speech Server days.

Here's a summary of what I ended up doing:

  • The multimethod factory generates a dynamic assembly on the fly. This assembly contains an automatically generated holder class encapsulating the delegate corresponding to each runtime overload of the multimethod plus a private invoker method for each overload. A central invoker method uses System.Type.InvokeMember to perform runtime method resolution while the private invokers perform marshalling and unmarshalling of arguments in and out of the runtime overload.
  • This implementation supports by-reference arguments such as ref and out parameters along with in parameters as well as return values, so it offers something much closer to a complete solution than my initial implementation.
  • The DebugInfo configuration class can be used to force the code generation phase to generate on-disc assemblies, symbols and pseudo-code which is provided to aid debugging of the generated IL: the code generation is somewhat fragile and it's very easy to leave the code generating "invalid program" errors when it gets JITted.
  • The on-disc assemblies can also be referenced in other solutions in order to use the generated multimethod without the overhead of the code/assembly generation phase.

For future investigation:

  • It would be nice to eliminate the reflection. As discussed at the recent PDC, there is a new planned dynamic pseudo-type in C# 4.0 which will allow for late-bound method calls. This is designed to improve COM interoperability but could just as well be applied to the problem of multiple dispatch. It would likely simplify a great deal of the IL that my multimethod factory has to generate.
  • Currently, the delegate types used to construct the multimethod have to be declared public since the dynamic assembly that implements the multimethod holder needs to be able to access these types at runtime. I would like to be able to remove this limitation in order to improve encapsulation.
  • I'm sure I could use abstract syntax trees and DLR-type on-the-fly code generation to do much of what can be done here. However, to remain compatible with .NET Framework 3.5 I'll be sticking with my reflection-based implementation for the time being!

Until next time…

MultipleDispatchRevisited.zip

Comments