Posts
208
Comments
1143
Trackbacks
51
C# 4.0 Optional Parameters

One of the new language features coming in C# 4.0 is Optional Parameters. In large part, this is due to Microsoft’s plan of co-evolution with C# and VB.NET since VB.NET has had this feature for a while.  Personally, I’m still somewhat undecided about this feature and there has been much written about method overloads versus optional parameters. For example, Considerations in Overloading Procedures.  Ultimately, I do think there will be some scenarios where this will be useful to make code more concise.

Consider a standard scenario with method overloading or constructor chaining.  In C# we’d have several methods with different signatures where, in effect, we’re really just after default values. Let’s take the scenario where we’ve got a little helper class to send emails in our application. In some cases we want to CC the administrator to troubleshoot issues; in some cases we want rich HTML emails rather than plain text. We might set up our methods like this:

   1:  public void SendMail(string toAddress, string bodyText)
   2:  {
   3:      this.SendMail(toAddress, bodyText, true);
   4:  }
   5:   
   6:  public void SendMail(string toAddress, string bodyText, bool ccAdministrator)
   7:  {
   8:      this.SendMail(toAddress, bodyText, ccAdministrator, false);
   9:  }
  10:   
  11:  public void SendMail(string toAddress, string bodyText, bool ccAdministrator, bool isBodyHtml)
  12:  {
  13:      // Full implementation here
  14:  }

This is pretty standard method overloading and we essentially are setting default values (true for CC the Admin, and false for HTML emails). With C# 4.0 we can now make the code more concise by only having to implement 1 method:

   1:  public void SendMail(string toAddress, string bodyText, bool ccAdministrator = true, bool isBodyHtml = false)
   2:  {
   3:      // Full implementation here
   4:  }

However, you do have to take into account your scenario.  If you have a situation where you actually need to know if the consuming code provided a value then this isn’t a good option because if “true” comes in for the 3rd parameter, you don’t know if the consuming code actually set this explicitly or if it was simply the result of the default value.  But in typical scenarios like this, it’s not a big deal.  Cracking open Reflector and looking at the IL that the C# compiler is generating:

   1:  .method public hidebysig instance void SendMail(string toAddress, string bodyText, [opt] bool ccAdministrator, [opt] bool isBodyHtml) cil managed
   2:  {
   3:      .param [3] = bool(true)
   4:      .param [4] = bool(false)
   5:      .maxstack 8
   6:      L_0000: nop 
   7:      L_0001: ret 
   8:  }

Which Reflectors translates to a C# equivalent of:

   1:  public void SendMail(string toAddress, string bodyText, [Optional, DefaultParameterValue(true)] bool ccAdministrator, [Optional, DefaultParameterValue(false)] bool isBodyHtml)
   2:  {
   3:  }

So if consuming code is written using the least specified “overload” like this:

   1:  email.SendMail("bob@foo.com", "Hello World");

The IL that the C# compiler will generate will actually be the equivalent of this:

   1:  email.SendMail("bob@foo.com", "Hello World", true, false);

What’s more interesting is that, unlike traditional method overloading, you have the ability to omit only the 3rd parameter in conjunction with the new Named Parameters language feature and write your code like this:

   1:  email.SendMail("bob@foo.com", "Hello World", isBodyHtml: true);

This will allow consuming code to only pass 3 arguments for succinctness but still invoke the appropriate overload since the IL generated in that instance will be equivalent to this:

   1:  email.SendMail("bob@foo.com", "Hello World", true, true);

Overall, it’s by no means an earth shattering feature that is being added to the language in stand-alone scenarios (though it will be have a *much* bigger impact in COM Interop).  Used in the correct scenarios, it can improve your code.

posted on Thursday, February 5, 2009 10:41 PM Print
Comments
Gravatar
# re: C# 4.0 Optional Parameters
Malisa Ncube
2/6/2009 3:19 AM
Nice article, i like the part where you can skip some and specify the rest.

email.SendMail("bob@foo.com", "Hello World", isBodyHtml: true);

the syntax is would have been nicer if we could use the = sign like

email.SendMail("bob@foo.com", "Hello World", isBodyHtml=true);

Thanks
Gravatar
# re: C# 4.0 Optional Parameters
RussellSprouts
7/6/2009 7:02 PM
You can't tell what that means though.
void Foo()
{
int a=6,b;
AddTenOrOther(a,b=7)
//Wait. Did I just assign the local variable b to 7, or call
//AddTenOrOther(3,7)
}
int AddTenOrOther(int a, int b=10)
{
return a+b
}
Gravatar
# re: C# 4.0 Optional Parameters
Steve
7/7/2009 7:59 AM
@RussellSprouts - The compiler won't let you do this line (probably for the same reason you stated above):

AddTenOrOther(a,b=7);

When calling a method like this that allows optional parameters in C# 4.0, you must use a colon instead of an equals sign (so as not to confuse it will assigning to a local variable as you mentioned):

AddTenOrOther(a,b:7);
Gravatar
# re: C# 4.0 Optional Parameters
Yoooder
8/21/2009 8:31 AM
Personally I've avoided optional parameters in VB.NET specifically because they've been missing from C#--not a big downfall since good method design dictates that methods should have as few parameters as possible (if you're passing 10 related fields they should probably be wrapped in a structure/class/DTO instead).

That said, there is one specific use I've found for the: they're great for unit-testing properties on DTO's with a large number of properties... I've added a post to my blog to detail this nicety: http://yoooder.com/wordpress/?p=62
Gravatar
# re: C# 4.0 Optional Parameters
Sean
10/8/2009 3:54 PM
Optional parameters are the sole biggest compiling problem we have. If you add an optional parameter to a function or sub there may be no need to change the code that calls the function. The compiler will not return an error for the calling code but the program will err when that function is called becuase it is expecting a different signature for that function or sub. It's easy to for get to look for calling functions when pushing out code changes and hard to debug beacuse everything looks like it is fine. I would recommend overloading functions to save from that headache.
Gravatar
# re: C# 4.0 Optional Parameters
Nalin D Jayasuriya
11/2/2009 4:07 PM
Optional method parameters are a deviation from fundamental object oriented design principals. Even though one could save a few lines of coding by avoiding the creation of overloaded methods, it’s best to stick to the widely accepted principals.

Also on a side note, it is a ‘best practice’ to have enumerations with meaningful values for true and false (boolean) rather than passing true or false as a method parameter value. To anyone that reads the code later the meaning of the parameter’s functionality is unknown. So for example, consider ‘MailFormat’ as an enumeration and define ‘Text’ and ‘HTML’ as values within the enumeration. Then pass MailFormat.Text or MailFormat.HTML as the parameter value rather than values true or false.
Gravatar
# re: C# 4.0 Optional Parameters
Kiran Cherupally
11/6/2009 1:50 AM
I have written a blog post on c# 4.0 optional parameters. Please read
http://cherupally.blogspot.com/2009/11/c-40-new-features-named-and-optional.html
Gravatar
# re: C# 4.0 Optional Parameters
Colin
3/18/2010 5:56 PM
I wonder why the syntax uses a : instead of an =... weird. Cool though and it's about time! Thanks for the post!
Gravatar
# re: C# 4.0 Optional Parameters
Pankaj
5/21/2010 8:05 PM
Optional Parameters feature was already present in Visual Basic. They have removed in .NET Framework 1.0,1.1,2.0 and 3.5.

Now in 4.0 it is there. I love feature..
Gravatar
# re: C# 4.0 Optional Parameters
DarkFader
7/21/2010 8:33 AM
omitting some parameters... reminds me a bit of object initializers.
new Blah { .a = 1, .c = 3 }.DoSomething();
Anyway, a cool feature. And I hope refactoring tools can remove the extra wrappers.
Gravatar
# re: C# 4.0 Optional Parameters
Richard
7/29/2010 8:18 AM
"it is a ‘best practice’ to have enumerations with meaningful values ... rather than passing true or false"

public enum MyClassSendMailMethodCcAdministrator
{
True,
False,
FileNotFound,
}

There are some situations where a domain-specific type makes sense, but in many cases a boolean is all you need. Replacing every bool parameter with a DST "just in case" is pointless.
Gravatar
# re: C# 4.0 Optional Parameters
Valeriano Cossu
8/27/2010 11:27 AM
In VB.net we have optional paratemers from the preistoric ages.. but now that I am a C# developer it's nice to see them again :)
Gravatar
# re: C# 4.0 Optional Parameters
Srinivas
12/7/2010 3:15 PM
I feel better to avoid using Optional parameters because in some cases when Optional parameters are uses in conjunction with Method overloading causes ambiguity for the complier.
Gravatar
# re: C# 4.0 Optional Parameters
Gaurav
7/3/2011 12:37 AM
check more : http://planetofcoders.blogspot.com/2011/06/c-optional-parameters.html
Gravatar
# re: C# 4.0 Optional Parameters
sk
7/28/2011 1:47 PM
Good one
Gravatar
# re: C# 4.0 Optional Parameters
rakesh
7/28/2011 1:48 PM
Nice Article
Very Helpfull

Thanks.

Post Comment

Title *
Name *
Email
Comment *  
Verification

View Steve Michelotti's profile on LinkedIn

profile for Steve Michelotti at Stack Overflow, Q&A for professional and enthusiast programmers




Google My Blog

Tag Cloud