Friday, April 10, 2009

Optional Parameter Gotcha!

Optional parameters are fake!! They don't exist. No really, they don't. They're merely a construct allowed by the compiler to reduce the number of needless overloaded methods a developer needs to create. When code that uses optional parameters gets compiled, the compiler takes the liberty of adding in any parameters you felt you didn't need to supply. You heard me! The substitution of optional parameters that are not implicitly supplied happens at compile time, not run time.

For instance, I have the following code:
Module Module1 Sub Main() Say() End Sub Sub Say(Optional ByVal what As String = "Hello World!") Console.WriteLine(what) End Sub End Module


The compiled version is a bit more interesting (converted from IL to VB):
Module Module1 <STAThread> _ Public Shared Sub Main() Module1.Say("Hello World!") End Sub Public Shared Sub Say(ByVal Optional what As String = "Hello World!") Console.WriteLine(what) End Sub End Module


Notice in the compiled version, that default value ("Hello World!") is supplied as a parameter to [Say]. Not a problem unless an assembly you haven't/can't deploy calls a method you just added an optional parameter for. Lets say we had an older version of my program where [Say] didn't take any parameters and just printed "Hello World!" to the screen. I decide later to get a little more modular and move [Say] to its own assembly. I update my program to use it the new method and everything is cool. Time goes by and I need a more generic version of [Say] so I add the [Optional what As String] parameter and deploy the modified assembly.

And then not too long later, I start getting informed from every person who happens to be using my assembly and calling [Say] that their applications are now blowing up.

Because the dependent applications weren't compiled with the new optional parameter in mind, they're trying to call a parameterless version of [Say] which, in reality, doesn't exist. Therefore, care should be taken when using optional parameters to maintain compatibility with assemblies that you can't/don't want to have to redeploy. In those situations, an overloaded method would be the best way to go.

I guess the beauty of optional parameters, as everything else, is only skin deep.

1 comment:

Wes said...

I'm aware of the formatting issue with the code. I'll get it fixed when I have access to FTP.