First Look at C#4.0 – Named Arguments

Posted: June 7, 2009 in .NET
Tags: ,

In my last post I had discussed about optional arguments and default values.In continuation to that today we will take a look into the named arguments feature.Let us consider the method definition and invocation as shown below:

class Program {
       static void Main(string[] args) {
           Foo f = new Foo();
           f.PrintName("Sankarsan", "S", "Bose");
   public class Foo {
       public void PrintName(string firstName, string lastName, string middleName ) {
           Console.WriteLine("Name is {0} {1} {2}", firstName, middleName, lastName);


Here the PrintName method is invoked using what is called positional arguments where the value of the parameters are determined by their position in the parameter list.In C# 4.0 we can do it like this using named arguments:

f.PrintName(lastName:"Sankarsan", firstName:"S", middleName :"Bose");

Here the method is invoked using the parameter names and their position in the parameter list of the method definition is of no consequence.The output here will be “S Bose Sankarsan”.Let us take a look at the IL code to understand what magic the compiler is doing behind the scenes.The IL code for the main method is shown below:

.method private hidebysig static void  Main(string[] args) cil managed
  // Code size       42 (0x2a)
  .maxstack  4
  .locals init ([0] class CSharp40Demo.Foo f,
           [1] string CS$0$0000,
           [2] string CS$0$0001,
           [3] string CS$0$0002)
  IL_0000:  nop
  IL_0001:  newobj     instance void CSharp40Demo.Foo::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldstr      “Sankarsan”
  IL_000c:  stloc.1
  IL_000d:  ldstr      “S”
  IL_0012:  stloc.2
  IL_0013:  ldstr      “Bose”
  IL_0018:  stloc.3
  IL_0019:  ldloc.0
  IL_001a:  ldloc.2
  IL_001b:  ldloc.1
  IL_001c:  ldloc.3
  IL_001d:  callvirt   instance void CSharp40Demo.Foo::PrintName(string,
  IL_0022:  nop
  IL_0023:  call       string [mscorlib]System.Console::ReadLine()
  IL_0028:  pop
  IL_0029:  ret
} // end of method Program::Main

For those who are not very much conversant with IL lsdtr  “Sankarsan” means load string with value “Sankarsan” into the evaluation stack and stloc.1 means store the value from evaluation stack to the second (0 based index) variable location. So here variable locations 1,2,3 contains values for the second,first and last parameter of the method.ldloc.2 stands from load from variable location 2 to program evaluation stack.So while actual method call ldloc.2,ldloc.1 and ldloc.3 is called in sequence matching the positional argument list.So this is also another syntactical sugar coat.

If I do something like

f.PrintName(lastName:"Sankarsan", middleName:"S", "Bose");

There will be a compilation error stating “Named argument specifications must appear after all fixed arguments have been specified”.The lines of code shown below is valid:

f.PrintName("Sankarsan", middleName:"S", lastName : "Bose");

Let us change the signature of this method a little bit adding some out and ref parameters as shown below:

public class Foo {
    public void PrintName(string firstName, string lastName, ref string middleName,out string error ) {
        error  = string.Empty;
        Console.WriteLine("Name is {0} {1} {2}", firstName, middleName, lastName);

This will call absolutely no problem because named parameters work fine with out and ref as well.

class Program {
    static void Main(string[] args) {
        Foo f = new Foo();
        string s = "S";
        string t = string.Empty;
        f.PrintName("Sankarsan",error:out t, middleName: ref s, lastName: "Bose");

So we have almost completed our discussion on Optional Arguments,Default Values and Named Parameters but the last question that remains is why suddenly after coming a long way C# design team felt the need of this in version 4.0.The answer is we have realized that we cannot do away completely with COM.For MS Office based applications and others, COM Interop is a necessity.These COM APIs have 20-30 arguments and at a time we need only few.Earlier we used the Type.Missing for other unused parameters no we have optional and named arguments to make our lives easier.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s