Should you declare methods using overloads or optional parameters in C# 4.0?

Greg Beech picture Greg Beech · Oct 30, 2008 · Viewed 21.1k times · Source

I was watching Anders' talk about C# 4.0 and sneak preview of C# 5.0, and it got me thinking about when optional parameters are available in C# what is going to be the recommended way to declare methods that do not need all parameters specified?

For example something like the FileStream class has about fifteen different constructors which can be divided into logical 'families' e.g. the ones below from a string, the ones from an IntPtr and the ones from a SafeFileHandle.

FileStream(string,FileMode);
FileStream(string,FileMode,FileAccess);
FileStream(string,FileMode,FileAccess,FileShare);
FileStream(string,FileMode,FileAccess,FileShare,int);
FileStream(string,FileMode,FileAccess,FileShare,int,bool);

It seems to me that this type of pattern could be simplified by having three constructors instead, and using optional parameters for the ones that can be defaulted, which would make the different families of constructors more distinct [note: I know this change will not be made in the BCL, I'm talking hypothetically for this type of situation].

What do you think? From C# 4.0 will it make more sense to make closely related groups of constructors and methods a single method with optional parameters, or is there a good reason to stick with the traditional many-overload mechanism?

Answer

Jon Skeet picture Jon Skeet · Oct 30, 2008

I'd consider the following:

  • Do you need your code to be used from languages which don't support optional parameters? If so, consider including the overloads.
  • Do you have any members on your team who violently oppose optional parameters? (Sometimes it's easier to live with a decision you don't like than to argue the case.)
  • Are you confident that your defaults won't change between builds of your code, or if they might, will your callers be okay with that?

I haven't checked how the defaults are going to work, but I'd assume that the default values will be baked into the calling code, much the same as references to const fields. That's usually okay - changes to a default value are pretty significant anyway - but those are the things to consider.