Optional Parameters and Named Arguments in C# 4 (and a cool scenario w/ ASP.NET MVC 2)

[In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu]

This is the seventeenth in a series of blog posts I’m doing on the upcoming VS 2010 and .NET 4 release.

Today’s post covers two new language feature being added to C# 4.0 – optional parameters and named arguments – as well as a cool way you can take advantage of optional parameters (both in VB and C#) with ASP.NET MVC 2.

Optional Parameters in C# 4.0

C# 4.0 now supports using optional parameters with methods, constructors, and indexers (note: VB has supported optional parameters for awhile).

Parameters are optional when a default value is specified as part of a declaration.  For example, the method below takes two parameters – a “category” string parameter, and a “pageIndex” integer parameter.  The “pageIndex” parameter has a default value of 0, and as such is an optional parameter:

image

When calling the above method we can explicitly pass two parameters to it:

image

Or we can omit passing the second optional parameter – in which case the default value of 0 will be passed:

image 

Note that VS 2010’s Intellisense indicates when a parameter is optional, as well as what its default value is when statement completion is displayed:

image

Named Arguments and Optional Parameters in C# 4.0

C# 4.0 also now supports the concept of “named arguments”.  This allows you to explicitly name an argument you are passing to a method – instead of just identifying it by argument position. 

For example, I could write the code below to explicitly identify the second argument passed to the GetProductsByCategory method by name (making its usage a little more explicit):

image

Named arguments come in very useful when a method supports multiple optional parameters, and you want to specify which arguments you are passing.  For example, below we have a method DoSomething that takes two optional parameters:

image

We could use named arguments to call the above method in any of the below ways:

image

Because both parameters are optional, in cases where only one (or zero) parameters is specified then the default value for any non-specified arguments is passed.

ASP.NET MVC 2 and Optional Parameters

One nice usage scenario where we can now take advantage of the optional parameter support of VB and C# is with ASP.NET MVC 2’s input binding support to Action methods on Controller classes.

For example, consider a scenario where we want to map URLs like “Products/Browse/Beverages” or “Products/Browse/Deserts” to a controller action method.  We could do this by writing a URL routing rule that maps the URLs to a method like so:

image

We could then optionally use a “page” querystring value to indicate whether or not the results displayed by the Browse method should be paged – and if so which page of the results should be displayed.  For example: /Products/Browse/Beverages?page=2.

With ASP.NET MVC 1 you would typically handle this scenario by adding a “page” parameter to the action method and make it a nullable int (which means it will be null if the “page” querystring value is not present).  You could then write code like below to convert the nullable int to an int – and assign it a default value if it was not present in the querystring:

image

With ASP.NET MVC 2 you can now take advantage of the optional parameter support in VB and C# to express this behavior more concisely and clearly.  Simply declare the action method parameter as an optional parameter with a default value:

C#

image

VB

image

If the “page” value is present in the querystring (e.g. /Products/Browse/Beverages?page=22) then it will be passed to the action method as an integer.  If the “page” value is not in the querystring (e.g. /Products/Browse/Beverages) then the default value of 0 will be passed to the action method.  This makes the code a little more concise and readable.

Summary

There are a bunch of great new language features coming to both C# and VB with VS 2010.  The above two features (optional parameters and named parameters) are but two of them.  I’ll blog about more in the weeks and months ahead.

If you are looking for a good book that summarizes all the language features in C# (including C# 4.0), as well provides a nice summary of the core .NET class libraries, you might also want to check out the newly released C# 4.0 in a Nutshell book from O’Reilly:

image

It does a very nice job of packing a lot of content in an easy to search and find samples format.

Hope this helps,

Scott

48 Comments

  • Awesome this will solve one of the main drawbacks I had with the readability of source code compared to something like Objective-C where you always put the named parameter in. e.g. 'dbCmd.CreateTable(true);' can now become 'dbCmd.CreateTable(Overwrite:true);' which IMHO is much more readable.

  • Wow. It's like some kind of voodoo magic. Will definately be including this in my talk about Vs2010 and .Net 4 to my colleagues next week.

  • Very cool. Just wondered about one thing. Are you allowed to have nullable parameters with default values?

    Lets say you have a method defined as Foo(int a, int? b=5). I would expect that calling Foo(4, null) explicitly in code wouldn't assign the default value of 5 because I'm actually providing a value, whereas calling Foo(4) would end up with b==5. Is this correct?

    if you ARE allowed nullable parameters then perhaps you need to add a warning to remind people not to do MVC actionmethods with nullable defaults, becasue then when called via reflection the value would still end up as null. I'm sure this would catch some peope out when converting over to this new syntax as it would be an easy mistake to make

  • fine

  • @Demis,

    The example you gave looks like a overkill to me..

    If a programmer is good enough to understand the code , then he will definety figure out what is "true" for i.e which parameter.

    my 2 cents

  • i have a pice of code:

    public ActionResult Index([Bind(Prefix = "Filter")] PrinterFilter Filter = null)
    {
    if (Filter != null)
    {
    ...


    and Filter is never null mvc 2 rc2; vs 2010 rc;

    am i missing something or it is a bug?

  • Great post Scott. I've been waiting for optional parameters in C#. The MVC example is excellent. I was working on a similar example today.

    I've just purchased the c# 4.0 book you've recommended above.

  • Very useful for MVC

  • What's your advice for a book on ASP.NET 4.0 (not only C#) ?
    Thanks

  • Nice article!!!

  • Currently the default controller factory doesn't play nicely with optional parameters in the constructor. Any plans on introducing these two pieces of functionality?

  • Well optional parameters are nice because they save a lot of work writing tons of method overloads which each need their own XML comment and Code Contract.

    Or don't they?

    Well, unfortunately, Mr FxCop doesn't like optional parameters. I guess the reason is the way they are implemented in the CLR. Modules that call a method with optional parameters in another library have to be recompiled if the default value of a parameter changes. This can of course lead to horrendous unforeseen issues.

    So I guess we have to wait for a cleaner concept and use the optional parameters feature only when we have to do some dirty work like talking to COM objects.

  • @Simon Yes you can use nullable defaults. Try this code:

    static void Main(string[] args)
    {
    blah();
    blah(1);
    blah(1, 2);
    blah(1, null);
    Console.WriteLine("---");
    blah(b: null);
    blah(1, b: 2);
    blah(a: 1);

    Console.ReadLine();
    }

    private static void blah(int a = 0, int? b = 0)
    {
    if (b != null)
    Console.WriteLine(b);
    else
    Console.WriteLine("null");
    }
    The output is:
    0
    0
    2
    null
    ---
    null
    2
    0

    Cheers

  • great examples, thanks ! looking forward to used 4.0

  • Would conversion of old code in VB.net that has optional Params to C# be breeze now?.

  • Nice article. It's great to see that optional parameters has finally made it into the language. I found it very useful at times when coding in VB.

  • How is this going to work with overloading of methods? I'm assuming you will not be able to create something like "GetProductsByCategory(string category, int pageIndex = 0)" and "GetProductsByCategory(string category)" as they would collide.

    Granted, I'm aware that my above example isn't the best choice to illustrate the problem, as the first method would more than likely handle the job of the second, but just using it as an example...

  • Where are the VS 2010 RTM bits? They should be up on MSDN by now.

  • Finally we got it... I was waiting for optional parameter support for a veryyyyy long time.

  • It should be mentioned that they both are compiler-only features (with some the help of Optional and DefaultParameterValue attributes). That means that method with one parameter with default value still cannot be used where parameter-less method is expected. So overloading is still required (but not so often). Additionally all assemblies that referenced method with default values must be recompiled if these defaults are modified. Otherwise old values are used.
    On the other hand the nice side-effect of it is ability to compile code for framework 3.5 that uses these features. It works only in VS2010, so it should not be used in public code. Unfortunately other nice new feature, dynamic type cannot be used in v3.5, because a supporting assembly is not available.

  • Nice to get it. Thank you, Scott!

  • Great! nice article, it's very useful in MVC

  • asp.net was really great for blogging than wordpress. 2 years before i am using wordpress but when i found blogs using asp i migrate to asp and now still using asp

  • Thank you Scott. Very nice blog

  • @Jacob Swanner:

    Why wouln't you simply create one method with the required parameter and one with an optional parameter? No need to create two methods, one being overloaded as they do the same thing with an optional parameter (beauty of this feature is to minimize code)

  • Some very exciting changes! Looks like Microsoft is closing the GAP between VB.NET and C# finally. I don't know about everyone else but I am going to have to start moving code to target C# 4.0 soon. :)

    Pete

  • Nice post Scott! Check out some of my blog post on C# 4 http://www.adilmughal.com/search/label/C%23%204.0

    Thanks!

  • Awesome! Named Argument surely come very handy. Also till this day we had to used a nullable parameter as a workaround since there was no optional parameter.

    Simply Great. Thanks a lot.

    Long Live Scott :)

  • C++ has already supported optional parameters.

  • Optional parameter is nice and i have studied it.
    Just one confusion is that isn't it effecting the overloading and OOPS concept?

  • Thank you scott. Great!

  • cool article and new technic

  • Should optional parameters not be used in 3.5 assemblies? I've been using VS2010 to build 3.5 assemblies for some time and thought the optional and named parameters were just compiler bonuses in VS2010.

  • It's interesting that we're seeing the gradual "C-Sharp-ification" of VB and the "VB-ification" of C#. Each languages cool things are being slowly integrated into the other.

  • Hi Scott,

    When will VS2010 RTM and when can we expect it on MSDN?

    Thanks!

  • Altough I think this is a great new feature in C#, I do have some worries about code quality. It's great not to have to write a method overload just because you want some parameter optional. However when omitting a parameter triggers a different code path from submitting the parameter, then there should be two overloads to the method still, in order to keep abstraction. I think it's something to include in our coding standards guide.

  • Nice article. It's clear now how to deal with optional parameters. Thank you!
    P.S. BTW. Always wanted to ask how are you making such nice round-cornered screenshots? :)

  • This is the Internet, so please could you add a link to the relevant part of the C# standard.

  • You might want to point out that because of the named-parameter change, parameter names are now considered to be part of your API. So it's not just the case that if you change your optional param that your client assemblies need to compile, you also need to be aware that changing the name of the parameter is now considered to be a breaking API change (even if the assembly will still work without recompile - the function call is still mapped to the right method. However, as soon as they do recompile, and _if_ those clients are using named parameters, they'll encounter errors). That's my understanding of the feature, mostly gathered from the newest edition of Effective C#.

  • Its about time C# caught up to VB in flexibility

  • Optional _Arguments_ and Named Arguments in C# 4 (and a cool scenario w/ ASP.NET MVC 2)

  • Very cool! C# should have this a long time ago.

  • One part of this feature bothers me: If the caller provides an argument for any one of a succession of optional parameters, it must provide arguments for all preceding optional parameters. Comma-separated gaps in the argument list are not supported.

    Is there a reason for this restriction? I was hoping this would work like it does in VB.

  • I thought C# already supported optional parameters in the form of method overloading?

  • Pretty cool.

    I think you meant Desserts, not Deserts.

  • Great news!!

    Similar to this optional parameter, if c# could support the InputBox() function as in VB, wouldn't that be awesome?

  • excellent presence on .net 4.0 good and wish you all the best.

  • If your stuck on .NET 3.5 you can achieve the same result using the DefaultValue attribute for example:

    public ActionResult Browse(string category, [DefaultValue(0)] int page)

    It's great that optional parameters are properly supported in C# in the .NET 4.0 framework though.

Comments have been disabled for this content.