Named arguments, optional arguments, and default values

C# 4.0 introduces the concept of optional parameter values into the language. Now, this has been a controversial subject in the past, and we have had many requests for the feature, but have traditionally stayed away from it. So, why now?

Well, before we get into the philosophy of why we decided to add it this time (which we will! I promise!), first lets discuss the feature itself.

I'll first let's talk about the features themselves, and will follow that with a brief discussion about the focus of C# 4.0 and how these features align with that focus. I'll expand in depth as to how each feature works, and what the compiler does behind the scenes in future posts.

Default parameter values

We've all had the experience of writing (or at least using) methods whose parameters are optional in nature. Often, those methods will contain overloads which will have the optional parameters removed, and will simply be a wrapper for the actual method, passing the default values that the library writer wants to provide for the method.

Default parameter values give us a way to explicitly declare the default value that we would like to be used for the parameter in the method signature itself, instead of in the forwarding method. This gives the added benefit of allowing the IDE to help out and inform the consumer of the default value for the given parameter.

These guys are specified in one of two ways:

public class C
    static void Foo([DefaultParameterValueAttribute(10)] int x, int y = 20) { }

The first mechanism is purely a backwards compatibility issue and an interop issue with COM and VB. We highly recommend against using this method, however, because it specifies that there is a default parameter value for the parameter, but does not specify that the parameter is in fact optional. This means that the default value given will never be used.

The second mechanism really says two things - first, it tells the compiler that this parameter is optional, meaning the user does not have to specify an argument in this position. Second, it gives the compiler the value to use when the user does not specify an argument for the parameter.

How default parameter values are encoded

Because the new syntax really does two things, it is encoded in the metadata as two things. We encode both the optional flag in the metadata signature (which is equivalent to using the OptionalAttribute attribute), and we encode the default value as the DefaultParmeterValueAttribute attribute.

These two mechanisms have already existed in the CLR, and are in fact what the VB compiler produces today, giving us an easy choice for how to encode the feature.

Note that the compiler will give you an error if you try to specify both a DefaultParameterValueAttribute attribute as well as a default value using the new syntax.

Also note that the compiler enforces that all optional parameters using the new syntax are specified after all required parameters.

Lastly, the compiler will not allow you to specify default parameter values for ref or out parameters. This is because there is no valid constant expression that is convertible to the ref or out type.

Optional arguments - how default parameter values are used

In order to make use of the default parameter values, we've added a feature which allows the caller to omit arguments for parameters which have default parameter values specified.

Notice that because we enforce that optional parameter values are specified at the end of the parameter list, you cannot omit an argument but specify an argument for a later position.

This means that even though existing libraries may have specified the DefaultParameterValueAttribute and the OptionalAttribute for a parameter in the middle of the list, the C# compiler will not allow you to call that method without specifying a value for that parameter.

You can kind of think of optional arguments as a params array - the compiler will allow you to call the method without specifying the arguments, but they must be at the end of the parameter list.

What gets code gen'ed?

First we need to note that the use of optional arguments is really just syntactic sugar. The compiler cannot generate a call without actually providing all the arguments - it simply provides an argument for you and allows you to omit specifying it.

Once the compiler realizes that you're calling a method and omitting an argument because it is optional, it takes the value specified in the DefaultParameterValueAttribute and encodes that as a constant value for the argument that you've omitted. Note that if you're calling a library that doesn't have a default value specified but is still optional, the compiler will use default(T) as the value, where T is the type of the parameter. Also note that for COM calls, we also allow you to omit arguments to ref parameters by generating the temporaries for you.

Putting it all together - Named arguments

The ability to omit specifying arguments for parameters that have a default value is really taken advantage of by the Named arguments feature. This feature allows you to specify by name the parameter for which you are providing a value. This means that you can now omit specifying arguments for all parameters, and only specify the ones which you actually care about.

For COM programmers, this is like heaven! I recently "got" to play with Office interop a bit, and found that the average method had 30 parameters! Most of the parameters are wonderfully optional, and with the ability to now omit them, code looks much cleaner and is much more readable.

Sorry, I'm getting ahead of myself. First let me describe the feature.

Named argument usage

This feature introduces new syntax at the call site of a method. Consider the following example:

public class ContactList
    List<Contact> SearchForContacts(
        string name = "any",
        int age = -1,
        string address = "any") { ... }

    static void Main()
        ContactList list = new ContactList();
        var x = list.SearchForContacts(age:26);

We've got some library method that searches through some contacts and finds the ones that match our criteria (I know, its a horrible API, but bear with me). The library is great! 😉 It specifies the default wildcards for us so that we can omit them as we wish. Now suppose we want to find all contacts aged 26.

Well, since we now have optional arguments, we can omit the arguments after the age parameter, but that gets us half way there. Named arguments get us the rest of the way.

By using the new syntax, we can specify by name the argument that we want to specify a value for, and omit the rest. The syntax is quite simple (well, not really, but I'll get into the details of its complexities later): simply specify the name of the parameter that you want to specify an argument for, add a colon, then add the value that you want.

Note that the value can be any expression type that you normally could have specified. Note also that named arguments are not restricted to parameters that are optional or have default values. Lastly, note that you don't even have to specify the arguments in order! We could call our method with the following:

list.SearchForContacts(address:"home", name:"sam", age:30);

The arguments don't have to be in any particular order. The only rule is that the named arguments must be specified at the end of the argument list. This means that all positional arguments (the "normal" ones that aren't specified by name) must be given first. Once the compiler encounters a named specification, it will produce an error upon encountering any further unnamed arguments.

So that's the feature in a nutshell. There are more details that I'll get to later, but in the mean time I'd love to get your feedback on the feature, on its uses, and on how we've chosen to design it.

And as always, happy coding!

kick it on

Comments (30)
  1. You’ve been kicked (a good thing) – Trackback from

  2. AtulGupta says:

    Good enhancements. Named arguments to me can also possibly make program more readable by making them as part of regular coding guidelines. Reading a name (a meaningful name offcourse) along with the value in a function call will enable quick understanding of what argument was expected and what is it that we are passing.

    So i guess this means better maintenance

  3. Thank you for submitting this cool story – Trackback from DotNetShoutout

  4. Omer van Kloeten says:

    Why not allow parameter values that come from instantiation or method calls? You could use code generation to create the overload.

  5. apinzur says:

    I’m very curious about the decision to resolve overload and parameter values at compile time. Wouldn’t deferring some of this until run-time give library authors more flexibility in maintaining backwards-compatibility between versions?

  6. samng says:


    Exactly! No more things like Print(false /*printHeaderInfo*/). Now we can do Print(printHeaderInfo:false);


    The problem there is that there is no way to specify in the attribute that we want to have a method call. Attribute arguments must be constants, and we’ve got to be back-compat with the current architecture that VB already has in place.


    Again, this is based on being compatible with the current architecture that’s already in place. In the same vein, you could argue that we should do all of overload resolution at runtime, so that the library implementer could provide more specific methods that will be called. We’ve already got a feature for that though – dynamic! 🙂

  7. Daniel Ziegler says:

    Shouldn’t that be list.SearchForContacts(address:"home", name:"sam", age:30); ?

  8. samng says:

    Great catch Ziegler! I’ve updated the entry to fix that. Thanks!

  9. One interesting side-effect of this is that it can also make it much easier to write immutable types, without requiring vast quantities of constructor overloads to cover different use-cases (and also enabling something like object initializer syntax).

  10. widdowsj says:

    C# is becoming more VB-like all the time.  Optional arguments have been part of VB for, what, 10+ years?  It’s been one of the arguments VB programmers have for why VB is better than C# (late binding is another that I also see is now becoming part of C# – dynamics).  Haven’t we been told that it’s better to write explicit overrides?  So why the switch now?  How long till the only difference between C# and VB is the semicolons at the end of the lines?  Not that I see it as a bad thing – just makes choice of language more of a moot point.

  11. Nullable says:

    As every new version of C# comes out, I wonder how I ever lived in the dark ages prior to C# v(current version here).

  12. S Satya D Bulusu says:

    I have a question here:

    Let us say there is a typo in the "SearchForContacts" method’s "name" parameter and the programmer mistyped it as "mane" (instead of "name") and say the library is released. As a client of that library I coded in my program such that "SearchForContacts(mane:"satya");

    In the later versions the parameter name is corrected (from "mane" to "name") and a new version of the library is released.

    Now I think my client doesn’t work with the new library. Am I correct here?

  13. Optional and named parameters特性在有些场合提供很大的方便,特别是Office开发中可以告别一坨System.Reflection.Missing了。这里简单了解一下C#4.0中的Optional and named parameters。

  14. samng says:

    Marc.gravell – You’re entirely correct with that thought. We’ve been giving immutable types a lot of thought, and while we haven’t decided anything in terms of the language, we definitely have thought a lot about features which would help achieve this goal.

    Widdowsj – You’re right in saying that we are co-evolving with VB. You should check out Anders’ talk at PDC about the Coevolution effort – he speaks more to the topic. Why the switch now – this release of C# focuses on interop, both between languages and platforms. COM interop is particularly a focus that we are taking this time around, and named arguments are a great asset to that technology.

    I believe that in the beginning, we believed COM would disappear with the introduction of .NET. Its been quite a few years since, and COM is still as widely used as ever. So we decided, if y’cant beat em, join em 🙂

    Bulusu – no, the client will work with the new library. The C# compiler does the reordering of arguments at compile time. This means that the IL generated looks as though you simply passed the parameter positionally. For example, suppose I have a method Foo(int x, int y) and I call it with Foo(y:10, x:20). The reordering of the names is compiler sugar – the IL generated looks as though you were calling Foo(20,10) instead of Foo(y:10, x:20).

  15. S Satya D Bulusu says:


    I am not sure I clerarly explained or not, but I am talking about the SPELLING of the parameter names in the prototype, not the ordering.

    For example:

    In version-1 of my Libray I have a method as follows:

    void foo(int x=10);

    Let us say I have a client calling as follows:


    Now in version-2 od my Libray the method is changed as follows:

    void foo(int y=10);

    But my client is not changed so it is still calling:


    I am just wondering it would casue any issues.

    As you know normally in any prgramming lanugage (as far as I know) we won’t depend upon the names of the calling method’s parameters. But with C# 4.0 we can and I was wondering that could cause any incompatibilities.

    Hope I explained clearly this time.


    Satya Bulusu

  16. samng says:

    Hi Satya,

    My apologies that my response was not clear. I understand the scenario you’re describing, and my response speaks to that scenario.

    In your client code, you call foo(x:20), but the IL that gets generated for this is foo(20). Notice that the IL has no trace of the name "x", nor does it have any trace of the named orderings that may be in your call site.

    Even though the v2 of your library changes the name, it is irrelevant – the IL doesn’t reflect the name at all.

    The names are only used as compile time sugars to tell the compiler explicitly which argument value is being specified. The compiler takes this information, uses it, and discards all traces of it in the IL stream generated.

    Hope that’s more clear!

    – Sam

  17. S Satya D Bulusu says:


    Thanks for the explanation. I am not sure how much you are bored with this blog 🙂 but here is another case I am wondering:

    Version-1 of my library:


    void foo(int x=0, int y=0);

    Client for the library:


    foo(y:20, x:10); ==C# Compiler==> foo(10,20) (Correct me if I am wrong)

    Version-2 of my library:


    void foo(int a=0, int b=0);

    Client for the library(not changed):


    foo(y:20, x:10);==> ? How does the compiler knows to map y for b and x for a?

    Am I missing any important point here?

    Hopefully answer to this question will stop me bothering you more on this blog 🙂



  18. samng says:


    When you say "Client for the library not changed", do you mean that you are not recompiling it? Or are you simply saying you’re not changing the source, but you ARE recompiling? If you are recompiling, then the compiler will give you an error saying that the name does not exist.

    Let me illustrate the steps:

    1) Compile version 1 of your library:

    void Foo(int a = 0, int b = 0);

    2) Compile the client code:

    Foo(b:20, a:10);

    3) Compile version 2 of your library:

    void Foo(int x = 10, int y = 20);

    4) Recompile your client code:

    Foo(b:20, a:10);

    Step 4 generates a compiler error.

    Hope that helps!

  19. reinux says:

    Nice feature. A useful addition without being a pedagogical nightmare.

  20. S Satya D Bulusu says:


    Yes, I am wondering about the scenario where a client is not recompiled, which I think is pretty understandable becasue the client might expect that a newer version of a library keeps its public method interfaces intact.

    But my dilemma here is that the new feature of C# might cuause clinets to throw Exceptions (MethodNotFound or some thing) and of cource eventual recompilation after fixing the prameter names might be able to let clients to work with the new version of the library where a method’s parameter names are changed.

    Hope I am explained my question clearly.



  21. Apple&#39;s OS X and iPhone language du jour Objective-C contains both archaisms and a number of excellent

  22. David.Wang says:

    Satya – the new feature is really not causing any additional issues. The problem you describe is with the library itself.

    Named arguments make the name, not order, of the argument important, even if the feature’s syntactic sugar makes it APPEAR that parameter ordering is important.

    Thus, if you want to use named values in a library, you should not remove/change the names or else clients will break. This exactly mirrors the original way of resolving method signatures — you should not remove/change the ordering of the types or else clients will break.

    The only confusion is that the syntax of named arguments make it APPEAR that ordering of types is important when it is not, and that seems acceptable. Changing external interface of a Library should not be done lightly.


  23. S Satya D Bulusu says:


    That is exactly what my point is. Implementing named arguments feature in a library will NOT let the library developers to rename the names of the library method arguments in the later releases as it could break clients using them in named arguments fashion.

    One might argue that "Named arguments are like method names in a library  and changing them would break clients just like changing the method names would break. So what is the big deal".

    My point is,  yes it might not be a big deal but this is new to programmers of C/C++/Java/C# (unitl now) who unitl now are careless about the argument names in a method’s signature that they call from their client. Now my understanding is they can’t be careless anymore. Please correct me if I am wrong.

    — Satya

  24. samng says:


    Using named arguments WILL let the library developers rename the names of library methods in later releases, and WILL NOT break old clients binding against the library, as long as the client is not recompiled.

    As David suggests, the feature is syntactic sugar that tells the compiler how to rearrange your arguments. When you compile your client, it loses all notion of named arguments.

    Suppose my library method is: void MyLibraryMethod(string mane, int age){}. Without named arguments, you would simply call the method as follows:

    MyLibraryMethod("Sam", 10);

    However, with named arguments, you can now call it like so:

    MyLibraryMethod(age:10, mane:"Sam");

    Now when you compile this, the compiler removes the fact that you gave a named specifier, and simply generates code for the following:

    MyLibraryMethod("Sam", 10);

    This means that changing the library method’s parameter name from "mane" back to "name" will have no effect on the client.

    Hope that helps,

    – Sam

  25. Xiaoth says:

    Looks like Objective-C inspiration to me.

  26. CFQüeb says:

    widdowsj wrote>

    "the only difference between C# and VB is the semicolons at the end of the lines? "…

    I don’t agree with the changes implemented in C#… sincerly.. each new version seems like VB more… what is the point?.. do wyou want that  VB programmers change to C# without says "nooooo" ???.. Implementing this similar features or codifying sintax.. the next step is drop VB and point to C# only… anyway.. :

    writeline("C#" == "VB" ? "Yes" : "Yes");


  27. Renaming your arguments in non-private/internal methods was always a bad idea, and they were always part of your public contract (with all the burden of versioning that comes with that) because any C# code you write may be used by client VB code (or other .NET language which has named arguments), so you will break things for them by renaming (not for compiled modules, but when recompiling, they will break). This has been true since the very first .NET release. It surprises me that C# developers only now realize that it is the case.

  28. Last time we talked about the basics of named arguments, optional arguments, and default values . From

  29. Okay, my attempt at a clever title failed… Ties and Philosophers? I oughtta stick with technical writing.

  30. sandeep says:

    ……..nice work….

Comments are closed.

Skip to main content