← all posts

Do you know Optional Parameters?

Gordon Beeming
Gordon Beeming

Up until about an hour ago I thought I knew how optional parameters worked but didn't actually. I thought (probably without giving it too much thought) that optional parameters would compile to something that would reflect having multiple overloads as when they came out I ripped out 100s of overloads across multiple libraries and replaces them with optional parameters because it replace code like

C# code showing multiple overloads of a GetMessage method
Multiple overloads of GetMessage method in C#.

with code like

C# code showing GetMessage method with optional parameters
GetMessage method using optional parameters in C#.

It's obviously that the second snippet is easier to read but do you know what's actually happening?

Andrew Clymer mentioned mentioned in training today that optional parameters are compiled into the calling code and not the method where they are used and thought this is something that others might not have known as well 🙂

See below for a quick example of this. Create a new Console Application and Class Library as below

Visual Studio solution with a Console Application and Class Library
Solution setup with Console Application and Class Library.

If you run this you will see in a console window the message Hello with some underscores.

Console output showing 'Hello _____'
Initial console output with default optional parameter value.

This is what we expect and there is nothing unusual there but what happens if we change the code for the Utils class like below

C# code in Utils class with changed optional parameter default value
Utils class with modified default value for the optional parameter.

Now build only the class library, copy the output assembly (CalcLibrary.dll) to the console windows output directory and then run the console window from windows explorer

Windows Explorer showing CalcLibrary.dll in the console app's output directory
Replacing CalcLibrary.dll in the console application's output directory.

You'll notice that again we see what we expect. Now change your Utils class to have underscores as a default in a name parameter and place that in the return string like this

C# code in Utils class with a new optional parameter 'name'
Utils class with an additional optional parameter 'name'.

Again if you run this you will get what you expect

Console output showing 'Hello _____' again
Console output remains unchanged after adding a new optional parameter with a default value.

Now lets make that second change we did and replace the underscores with a underscore dash repeated 5 times like so

C# code in Utils class with modified default value for 'separator' optional parameter
Modifying the default value of the 'separator' optional parameter in Utils class.

Build just the class library, copy the assembly over and run the console app in windows explorer and you'll see that the nothing changed in the console window

Console output still showing 'Hello _____' after changing the class library
Console output does not reflect the change in the class library's optional parameter default value without recompiling the console app.

I recently watch Bart De Smet's Pluralsight videos (C# Language Internals - Part 1 | C# Language Internals - Part 2) and one thing I realized is that I thought I knew stuff and to almost truly know you should check the IL or view the IL in a nice tool like IL Spy. So I opened the code in IL Spy and took a look at the class library to make sure that it update and as expected it did

IL Spy showing the decompiled C# code of the updated CalcLibrary.dll
IL Spy showing the updated default value in the decompiled CalcLibrary.dll.

and to then opened the program class in the class library and found that the code that the console app was compiled against had been added to the call to Utils.GetMessage

IL Spy showing the decompiled C# code of the console application, revealing the old default value is compiled in
IL Spy showing the console application's compiled code still using the old default value for the optional parameter.

In this example there is nothing that could go wrong and you probably would worry about the behavior of the optional parameter but there will be cases in more important code where this could be a problem maybe for performance or even security I'm guessing.

Gordon Beeming
Gordon Beeming

Father • Husband • Triathlete • SSW Solution Architect

Related posts