Iris Classon
Iris Classon - In Love with Code

Is use of default parameters/optional arguments a bad practice in C#? (Q263)

Almost a month ago I was out at a client waiting for some feedback from a few meetings and got into a discussion with another developer about default parameters. I decided to bring the discussion to Twitter and Facebook to hear some more opinions. Here is a quick write-up :)

The following bit is a summary of the discussion, I also had a read on the four-part blog post by Eric Lippert which of course added further to the discussion. If something is missing or incorrect, please let me know.

2013-12-29 23-56-52

Introduced when, and why

Optional arguments, also referred to as default parameters, were introduced with C# 4, and as one dev put it ‘I use them but always feel a little dirty afterwards.’ I can relate, and optional arguments have caused a few debates. I was surprised to see that the majority of the devs that replied to the Tweet gave the thumbs up,- there is nothing wrong with using them as long as you take some precautions. And after seeing the replies, I now agree. This was a highly requested language feature that would let us avoid overloading of methods, and therefore have less code to maintain and hopefully introduce less defects.

2013-12-30 02-03-05

The discussion

Optional arguments help us avoid a long list of overloaded methods. You can extend an existing method by adding some arguments that have default value instead of writing an identical method with different parameters. This is also where you want to be careful if you decide on either changing the default value in a library or adding optional arguments in a method to an existing library. It’s also good to keep in mind that if your method has many optional arguments it might be doing too many things, which indicates that you need to look over your code and break things down into tinier pieces. (Use of flags is also a good indicator that there might be a better way to solve that particular problem, but that is a different discussion).

Optional arguments also have a peculiar behavior when used with interfaces. Even if you have specified a default parameter in the interface, you can ignore it on the class that implements the interface. If you have two interfaces that both define the same method with the same default parameters but different values you would need to access the method through the interface and the method that has the value you want to be used (- I didn’t know about this before I read Eric’s blog series on the topic, he has some example worth checking out).

On a side note

Optional arguments should not be confused for the param arrays (allows you to pass n number of arguments to a method)- we are talking about two completely different things and it is important to understand the difference. If you don’t know how manyarguments the user will pass in, use a param array, if you need to set default values, use optional arguments. If you need both, use both, but you cannot set a default value for a param array in the method declaration.

Comments

Leave a comment below, or by email.
Peter Morlion
12/30/2013 4:40:01 PM
I wonder if people (including myself) would feel as dirty if this would have been a feature of C# from the beginning. I tend to think not. I'd say use them if you can. But watch out for too may parameters on your method. But that goes for traditional overloads as well. 
Iris Classon
12/30/2013 6:54:10 PM
Reply to: Peter Morlion
That is a very good point! And its very easy to clutter up the parameters, and what should have been a class with a semi-busy constructor becomes a super-method instead. 
Bruno Brant
12/30/2013 7:30:28 PM
The problem boils down to the fact that default parameters are baked into callers instead of callees. This means that future maintenance of the code can change the default value on one assembly and all of sudden you have unexpected behavior in your application. 

I have a (rather strong)  C++ background, so default parameters are very common to me. However, given the dynamism in managed languages, the reuse of libraries and partial updates of LOB applications, I'm now very afraid of default parameters. I use them on internal classes only, or, on peculiar cases, in public classes for reference types (which can only be assigned null). 

I just wish MSFT implemented it differently, baking the value into the method metadata or even doing some hard lifting and creating multiple methods. 
Piotr Perak
12/31/2013 11:21:49 AM
Reply to: Bruno Brant
This should be mentioned in the post. Because this is what is wrong and that's why I don't ever use default parameters. C# creators ommited implementing default parameters because they thought they were bad. Now they included it. I don't like it. 
Frederic Torres
1/1/2014 12:14:01 PM
Reply to: Bruno Brant
If I add a new optional parameter to a method, it is my responsibility that the default value implement the previous behavior, therefore there is no unexpected behavior.

Plus previous unit tests should catch any breaking changes. 
Iris Classon
1/1/2014 5:48:10 PM
Reply to: Piotr Perak
it is mentioned in the post but I will make sure it is more clearly, I've done a poor job there so thank you for pointing that out. I also only use them (if I do) on internal classes, but usually end up breaking my code up as the method seems to grow in size and functionality. I do wish I knew C++ because it would be very interesting to compare. Let me know if any of you write about that, I would love to link that here. 
Kevin Watkins
1/2/2014 6:12:04 AM
Another one to watch out for is constructors. For example:

public class SomeClass
{
    public SomeClass(bool something = true)
    {
    }
}

Although I can instantiate this with new SomeClass() it doesn't have a public parameterless constructor. Which means this will fail:

private static void DoSomething()
    where T : new()
{
}

DoSomething();

Similarly doing Activator.CreateInstance() will fail; this caught me out recently. 
Chris Marisic
1/2/2014 2:51:40 PM
I find optional/default parameters to be absolutely awesome used well.

In general i always have class similar to 

public class Foo {
public Foo() : this(null,null){}
public Foo(IEnumerable ints = null, IEnumerable bars = null)
{
if(ints != null) _ints = new List(ints);
if(bars != null) _bars = new List(bars);
}

To handle initialization.

With methods, i always attempt to create as few overloads as possible by sane usages of optional parameters. 


Also something wierd about the comment form prevents me from entering my name or email in firefox, i had to switch to chrome. 
K. Alan Bates
2/20/2014 4:05:18 PM
Total nay on optional arguments. They're nice bandaids to allow you to extend as functionality expands and exposes flaws in your architecture, but that's what they should be treated as: markers of flaws in your architecture.  

Default/Optional parameters = code smell. 
José Manuel Nieto
2/26/2014 3:25:40 PM
I think it's a good question. I never thought about it. As a Clean Code lover, I tend to think that optional parameters are a feature to avoid. Defaults sometimes are not clear. Making things explicit as normally a good ideal. 

However, it can be useful for a few situations like short utility methods that do common tasks widely understood, without hiding the meaning or causing ambiguity. 
Nick
4/7/2014 8:07:25 AM
Reply to: Peter Morlion
Many people don't like using optional parameters in VB.net and it has always had optional parameters so I don't think it would make any difference if C# had optional parameters from the beginning. 
Zach
4/5/2016 7:24:51 AM
I say no thanks to optional parameters.
An optional parameter indicates two or more decision paths.
IMO this will violate one's desire to write single responsibility methods.

The only use case I've ever seen for optional parameters are when trying to retrofit legacy code.

Also, consider the .net framework. Do you see lots of overloaded methods in the api's or optional methods?
I strongly recommend checking out the Framework Design Guidelines book that was written from the .net guys. 


Last modified on 2013-12-29

comments powered by Disqus