Versioning and optional parameters
The restrictions on default values for optional parameters may remind you of the restrictions on const fields or attribute values, and they behave very similarly. In both cases, when the compiler references the value, it copies it directly into the output. The generated IL acts exactly as if your original source code had contained the default value. This means if you ever change the default value without recompiling everything that references it, the old callers will still be using the old default value. To make this concrete, imagine this set of steps:
- Create a class library with a class like this:
public class MyDemo { public static void PrintValue(int value = 10) { System.Console.WriteLine(value); } } - Create a console application (Application.exe) that references the class library:
public class Program { static void Main() { MyDemo.PrintValue(); } } - Run the application—it’ll print 10, predictably.
- Change the declaration of PrintValue as follows, then recompile just the class library:
public static void PrintValue(int value = 20)
- Rerun the application—it’ll still print 10. The value has been compiled directly into the executable.
- Recompile the application and rerun it—this time it’ll print 20.
This versioning issue can cause bugs that are hard to track down, because all the code looks correct. Essentially, you’re restricted to using genuine constants that should never change as default values for optional parameters. There’s one benefit of this setup: it gives the caller a guarantee that the value it knew about at compile-time is the one that’ll be used. Developers may feel more comfortable with that than with a dynamically computed value, or one that depends on the version of the library used at execution time.
Of course, this also means you can’t use any values that can’t be expressed as constants anyway—you can’t create a method with a default value of “the current time,” for example.
