#595 – Intellisense Shows Method Overloads

When you overload a method, you’re creating multiple methods with the same name, but a different number of parameters, or parameters of different types.  At compile-time, the compiler will automatically call the correct method.

Visual Studio can help with entering parameter values.  When you enter the name of a method, Intellisense shows you a list of available methods with that name.

Let’s say that we have three different versions of a Dog.Bark method.  After typing “Bark” and the opening parenthesis “(“, Intellisense will indicate that there are three versions of the method available and provide information about the first version.

At this point, you can press the up/down arrow keys to cycle through the three different methods.

Notice that Intellisense does the following:

  • Indicates in bold the next parameter that you should enter
  • Lists a description of the method, if one is available
  • Provides a description of the next parameter

#594 – When You’d Want to Use Named Arguments

You can change the  order of arguments passed to a method in C# by using named arguments.  Simply changing the order of required arguments probably doesn’t make much sense.  Instead, you’ll likely make use of named arguments as a way of omitting optional parameters.

Without named arguments, when you want to include a value for an optional parameter, you normally have to include values for all arguments up to and including the one that you want to specify a value for.  But with named arguments, you can pick and choose which parameters you provide a value for.

Here’s a Dog.Bark method that has several optional parameters.

public void Bark(string barkSound, int numTimesToBark = 1, int volume = 1, string postBarkSound = null)

When calling Bark, we can choose which arguments to pass.

kirby.Bark("Woof", volume: 5);
kirby.Bark("Grrr", postBarkSound: "Arf");
kirby.Bark("Woof", 3, postBarkSound: "Growf");

#593 – Using Named Arguments

Traditionally in C#, arguments must be passed in to a method in the same order in which they are defined in the method’s declaration.

public void DoATrick(string trickName, int numTimes)
            Dog kirby = new Dog("Kirby");

            kirby.DoATrick("Fetch", 158);

You can, however, change the order of the arguments by preceding each value by the name of the parameter, with a colon (:) following each name.

            kirby.DoATrick(numTimes: 5, trickName: "Run around me");

#592 – Optional Parameters in Indexers

In addition to defining optional parameters within methods, you can also include an optional parameter in an indexer.

For example, assume that we have a Dog class that keeps track of the sounds that a dog makes when he barks and that we’ve defined an indexer for the class that retrieves a “bark sound” from that list.

        public string this[int i]
        {
            get
            {
                return BarkRecord[i];
            }
        }

Using the indexer:

            kirby.Bark("Woof");
            kirby.Bark("Bow-wow");
            kirby.Bark("Urgh");

            Console.WriteLine(kirby[2]);


We can now add an optional parameter to the indexer, to indicate that we’d like the date/time of the bark returned as well.

        public string this[int i, bool includeTime = false]
        {
            get
            {
                string barkInfo = BarkRecord[i];

                if (includeTime)
                    barkInfo = barkInfo + string.Format(" at {0}", BarkTime[i]);

                return barkInfo;
            }
        }

Using the indexer:

            Console.WriteLine("Bark at [2]={0}", kirby[2]);
            Console.WriteLine("Bark at [1]={0}", kirby[1, true]);

#591 – How Optional Parameters Look with Intellisense

When you’re working in Visual Studio and you start typing in the name of a method, Intellisense will show you any optional parameters that the method has.

In the example below, we’ve started entering code to create a new instance of a Dog object.  Intellisense shows us a list of the optional parameters that are defined for the constructor.

#590 – Optional Parameters in Constructors

You’ll typically see optional parameters in methods.  But you can also define an optional parameter in a constructor:

        public string Name { get; set; }
        public int Age { get; set; }
        public string FavoriteToy { get; set; }
        public Dog Father { get; set; }
        public Dog Mother { get; set; }

        public Dog(string name, int age = 1, string favToy = "Bone",
            Dog father = null, Dog mother = null)
        {
            Name = name;
            Age = age;
            FavoriteToy = favToy;
            Father = father;
            Mother = mother;
        }

 

            Dog kirby = new Dog("Kirby", 15, "Ball");
            Dog sonOfKirby = new Dog("Ferbie", 2, "Frisbee", kirby);


Optional parameters in constructors avoid the need to chain constructors.

 

#589 – Optional Parameters Must Be Input Parameters

An optional parameter must be an input parameter.  It can’t therefore be modified by the out or ref keywords.  An optional parameter also cannot be modified by the params keyword.

        // OK: numTimesToRead is an input parameter (passed by value)
        static void ReadBook(string title, int numTimesToRead = 1)
        {
        }

        // NO: out parameter can't have default value
        static void ReadBook2(string title, out int yourRating = 3)
        {
            yourRating = 4;
        }

        // NO: ref parameter can't have default value
        static void ReadBook3(string title, ref string yourOpinion = "Unknown")
        {
        }

        // NO: Parameter array can't have default value
        static void ReadBook4(string title, params string[] characters = null)
        {
        }

#588 – A Default Parameter Value Can Be Null

When defining optional parameters and providing a default value for the parameter, you can use a value of null for a reference-typed parameter.  null is actually the only valid default value that you can use for a reference-typed parameter.

        static void LogDogInfo(Dog myDog, Dog anotherDog = null)
        {
            Console.WriteLine("My dog is {0}", myDog.Name);
            if (anotherDog != null)
                Console.WriteLine("  And there is also {0}", anotherDog.Name);
        }

        static void Main()
        {
            Dog dog1 = new Dog("Kirby", 15);
            Dog dog2 = new Dog("Jack", 17);

            LogDogInfo(dog1);
            LogDogInfo(dog2, dog1);
        }

#587 – If Provided, Optional Arguments Must Be in Correct Order

When you choose to include arguments for optional parameters on a method, you must specify the arguments in the proper order (just like required parameters).

In the example below, we define a method with one required parameter and three optional parameters.  When we call it, we must provide a value for the yourName parameter.  Then we can provide values for one, two or all three of the optional parameters, in the following combinations:

  • book
  • book, play
  • book, play, poem
        static void Favorites(
            string yourName,
            string book = "Moby Dick",
            string play = "Henry V",
            string poem = "The Road Not Taken")
        {
            Console.WriteLine("{0}'s favorites:", yourName);
            Console.WriteLine("  Book: {0}", book);
            Console.WriteLine("  Play: {0}", play);
            Console.WriteLine("  Poem: {0}", poem);
        }

        static void Main()
        {
            Favorites("Sean");
            Favorites("Sergei", "Anna Karenina");
            Favorites("Pablo", "Don Quixote", "Canción de cuna");
            Favorites("Nigel", "David Copperfield", "Hamlet", "Ode to Duty");
        }

#586 – Default Values for Optional Parameters Must Be Constants

When you specify a default value for an optional parameter, that value must be a constant, of the same type as the parameter.  The expression must be able to be evaluted at compile-time.  The parameter’s default value can be one of the following:

  • A constant expression (see below)
  • new S(),  where S is a value-type (parameters not allowed on constructor)

A constant expression is one that can be fully determined at compile-time.  In other words, you can use any expression that you’d use in the initialization of a constant.

For reference types, the expression must be null, with the exception of the string type.

        private const int OFFSET = 1;

        static void Optional1(int x = 5 + OFFSET, double y = 1.0/3.0) { }
        static void Optional2(Point3D fln = new Point3D()) { }
        static void Optional3(Dog d = null) { }
        static void Optional4(string s = "DEFAULT") { }

        static void Main()
        {
            Optional1();
            Optional2();
            Optional3();
        }