How Optional Parameters work, why they can be dangerous, and why they work in .net 2/3 as well
One of the changes I really like in Visual Studio 2010 are optional parameters to method. Basically they allow you to specify a default value for each parameter and thus reduce the number of overloads to a method. Make sure to read to the end as there is a huge word of caution regarding optional parameters.
Instead of having this:
private static string SomeMethod(int value)
{
return SomeMethod(value, "Was Empty");
}
private static string SomeMethod(int value, string data)
{
return string.Format("{0}: {1}", value, data);
}
You can just have this:
// static because it's a console app, no extra magic
private static string OptionalMethod(int value, string data = "Was Empty")
{
return string.Format("{0}: {1}", value, data);
}
The nice thing about this feature is that it also works with .net 2/3. Why? Because it is implemented like this:
private static string OptionalMethod(int value,
[Optional, DefaultParameterValue("Was Empty")] string data)
{
return string.Format("{0}: {1}", value, data);
}
Looks like a normal method (the longest overload) with some attributes. Are those attributes the magic? No, it's much simpler. If this is your calling code:
Console.WriteLine(OptionalMethod(1));
Console.WriteLine(OptionalMethod(2,"Test"));
Then this is how it looks in the compiled assembly:
Console.WriteLine(OptionalMethod(1, "Was Empty"));
Console.WriteLine(OptionalMethod(2, "Test"));
As you see, the compiler changes the method call to put in all optional parameters into the caller. This explains why this works with pre-.net 4 applications. However, this also explains the huge warning I want to give:
Changing the optional parameter value will not change the behavior of your callers!
Imagine you want to change the value to "No value specified". With the overload solution this is trivial:
private static string SomeMethod(int value)
{
return SomeMethod(value, "No value specified");
}
Recompile your provider assembly and every consumer who uses that overload will get the new value. However, with optional parameters you have to re-compile each and every consumer assembly as well, so changing an optional parameter is a big, breaking change.
Does that mean that Optional Parameters are evil and should be avoided at all costs? Some people might think so, but I think they are useful for variables that almost never change. Think about a function like SendMail(string server, int port = 25)
.