First Look at C# 4.0 – Optional Parameters and Default Values

Posted: May 31, 2009 in .NET, C#
Tags: ,

I have recently downloaded the Visual Studio 2010 Beta 1 and started looking into the .NET Framework 4.0/IDE features.In the next couple of posts I will be discussing about these.To start with I have chosen optional parameters and default values.This feature is nothing new and has been there in languages like C++ for quite long.We will first take a look how we can use this in C# and how it is implemented.The following lines of C# code shows a method where the parameter middleName is optional and client is forced to pass a blank string value there as the parameter is not optional.

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

In C# 4.0 we can specify a default value for the parameter middleName and make it optional parameter as shown below.

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

This code will not compile and throw the error,Optional parameters must appear after all required parameters.This is Rule#1: we have to define all the optional parameters after required parameters they cannot appear in between some required parameters.

So the let’s change the parameter ordering as shown below:

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

This time I get another compilation error,Default parameter value for ‘middleName’ must be a compile-time constant.This is Rule#2:we have to use compile time constant as default values.So we alter the code as,

public void PrintName(string firstName, string lastName,string middleName="") {
    Console.WriteLine("Name is {0} {1} {2}", firstName, middleName, lastName);
}

This code will work fine and print “Name is Sankarsan Bose”.

Let us take a look at the IL code to find out what’s going on behind the scenes.The IL code for PrintName is shown below:

.method public hidebysig instance void  PrintName(string firstName,
                                                  string lastName,
                                                 [opt] string middleName) cil managed
{
  .param [3] = “”
  // Code size       16 (0x10)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      “Name is {0} {1} {2}”
  IL_0006:  ldarg.1
  IL_0007:  ldarg.3
  IL_0008:  ldarg.2
  IL_0009:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object,
                                                                object,
                                                                object)
  IL_000e:  nop
  IL_000f:  ret
} // end of method Foo::PrintName

The [opt] indicates this is an optional argument and param[3]=”” provides the default value.The IL code of the main function will look something like this:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       36 (0x24)
  .maxstack  4
  .locals init ([0] class CSharp40Demo.Foo f)
  IL_0000:  nop
  IL_0001:  newobj     instance void CSharp40Demo.Foo::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldstr      “Sankarsan”
  IL_000d:  ldstr      “Bose”
  IL_0012:  ldstr      “”
  IL_0017:  callvirt   instance void CSharp40Demo.Foo::PrintName(string,
                                                                 string,
                                                                 string)

  IL_001c:  nop
  IL_001d:  call       string [mscorlib]System.Console::ReadLine()
  IL_0022:  pop
  IL_0023:  ret
} // end of method Program::Main

Take note of the lines marked in bold.The compiler is checking the method signature of PrintName and generating IL code to call a method with 3 parameters and passing the default value as the argument.So this again is nothing but a syntactical sugar coat.

If we add one more method with same name and two string parameters as shown below, which method will be called?.

public void PrintName(string firstName, string lastName) {
    Console.WriteLine("PrintName2::Name is {0} {1}", firstName, lastName);
}

Here we are calling PrintName with two arguments so .The output is PrintName2::Name is Sankarsan Bose, the method without optional parameters will be considered in this case.

This is all about optional parameters, in the next post we will discuss about named arguments.

Advertisements
Comments
  1. Invaboobe says:

    I don’t know If I said it already but …Cool site, love the info. I do a lot of research online on a daily basis and for the most part, people lack substance but, I just wanted to make a quick comment to say I’m glad I found your blog. Thanks, 🙂

    A definite great read..

  2. ashishmgupta says:

    Optional parameters wont work in functions making use of “params” parameters as the params parameters have to be the last parameter in the list.

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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