// The finally Block
        // ---------------------------------------------------------------------------------------------------------------
        // A try/catch scope may also define an optional finally block.The purpose of a finally block is to ensure
        // that a set of code statements will always execute, exception(of any type) or not.To illustrate, assume you
        // want to always power down the car’s radio before exiting Main(), regardless of any handled exception.

        // In a more real-world scenario, when you need to dispose of objects, close a file, or detach from
        // a database(or whatever), a finally block ensures a location for proper cleanup.
        public static void ExampleCar54()
        {
            Console.WriteLine("***** Handling Multiple Exceptions *****\n");
            Car5 myCar = new Car5("Rusty", 90);

            myCar.CrankTunes(true);
            try
            {
                // Speed up car logic.
            }
            catch (CarIsDeadException e)
            {
                // Process CarIsDeadException.
            }
            catch (ArgumentOutOfRangeException e)
            {
                // Process ArgumentOutOfRangeException.
            }
            catch (Exception e)
            {
                // Process any other Exception.
            }
            finally
            {
                // This will always occur. Exception or not.
                myCar.CrankTunes(false);
            }
        }
        // Rethrowing Exceptions
        // ---------------------------------------------------------------------------------------------------------------
        // Be aware that if the Method is the Main() method, the ultimate receiver of Exception is the CLR because it
        // is the Main() method rethrowing the exception.Because of this, your end user is presented with a system
        // supplied error dialog box.Typically, you would only rethrow a partial handled exception to a caller
        // that has the ability to handle the incoming exception more gracefully.

        // Notice as well that you are not explicitly rethrowing the Exception object but rather making
        // use of the throw keyword with no argument. You’re not creating a new exception object; you’re just
        // rethrowing the original exception object (with all its original information). Doing so preserves
        //  the context of the original target.
        public static void ExampleCar53()
        {
            Console.WriteLine("***** Custom Exception Example53 *****");
            Console.WriteLine("=> Creating a car and stepping on it!");
            Car5 myCar = new Car5("Zippy", 90);

            myCar.CrankTunes(true);
            try
            {
                // trip exception
                myCar.Accelerate(-10);
            }
            catch (Exception ex)
            {
                throw;
            }
            // The error has been handled, processing continues with the next statement.
            Console.WriteLine("\n----------- Out of exception logic ----------- ");
            // separator
            Console.WriteLine("".PadLeft(40, '='));
        }
        // Exception Filters
        // ---------------------------------------------------------------------------------------------------------------
        // C# 6 introduced a new clause that can be placed on a catch scope, via the when keyword. When you add
        // this clause, you have the ability to ensure that the statements within a catch block are executed only if some
        // condition in your code holds true. This expression must evaluate to a Boolean (true or false) and can be
        // obtained by using a simple code statement in the when definition itself or by calling an additional method in
        // your code.In a nutshell, this approach allows you to add “filters” to your exception logic.
        // First, assume you have added a few custom properties to your CarIsDeadException.
        public static void ExampleCar55()
        {
            Console.WriteLine("***** Exception Filtering with When Clause Test55 *****");
            Console.WriteLine("=> Creating a car and stepping on it!");
            Car5 myCar = new Car5("Zippy", 90);

            myCar.CrankTunes(true);
            try
            {
                // trip exception
                myCar.Accelerate(-10);
            }
            catch (CarIsDeadException ex) when(ex.ErrorTimeStamp.DayOfWeek != DayOfWeek.Friday)
            {
                Console.WriteLine($"-------------- CarIsDeadException, when day is not Friday --------------");
                Console.WriteLine($"ex.Message         : {ex.Message}");
                Console.WriteLine($"ex.ErrorTimeStamp  : {ex.ErrorTimeStamp}");
                Console.WriteLine($"ex.CauseOfError    : {ex.CauseOfError}");
            }
            catch (ArgumentOutOfRangeException ex)
            {
                Console.WriteLine($"-------------- ArgumentOutOfRangeException --------------");
                Console.WriteLine($"ex.Message         : {ex.Message}");
            }
            // This will catch any other exception
            // beyond CarIsDeadException or
            // ArgumentOutOfRangeException.
            catch (Exception e)
            {
                Console.WriteLine($"-------------- Exception --------------");
                Console.WriteLine(e.Message);
            }
            // The error has been handled, processing continues with the next statement.
            Console.WriteLine("\n----------- Out of exception logic ----------- ");
            // separator
            Console.WriteLine("".PadLeft(40, '='));
        }