Last modified on 21 July 2014, at 17:20

C# Programming/The .NET Framework/Console Programming

Console ProgrammingEdit

InputEdit

Input can be gathered in a similar method to outputing data using the Read() and ReadLine methods of that same System.Console class:

using System;
public class ExampleClass
{
   public static void Main()
   {
       Console.WriteLine("Greetings!  What is your name?");
       Console.Write("My name is: ");
       string name = Console.ReadLine();

       Console.WriteLine("Nice to meet you, " + name);
       Console.ReadKey();
   }
}

The above program requests the user's name and displays it back. The final Console.ReadKey() waits for the user to enter a key before exiting the program.

OutputEdit

The example program below shows a couple of ways to output text:

using System;

public class HelloWorld
{
   public static void Main()
   {
       Console.WriteLine("Hello World!");             // relies on "using System;"
       Console.Write("This is...");
       Console.Write(" my first program!\n");
       System.Console.WriteLine("Goodbye World!");    // no "using" statement required
   }
}

The above code displays the following text:

Hello World!
This is... my first program!
Goodbye World!

That text is output using the System.Console class. The using statement at the top allows the compiler to find the Console class without specifying the System namespace each time it is used.

The middle lines use the Write() method, which does not automatically create a new line. To specify a new line, we can use the sequence backslash-n (\n). If for whatever reason we wanted to really show the \n character instead, we add a second backslash (\\n). The backslash is known as the escape character in C# because it is not treated as a normal character, but allows us to encode certain special characters (like a new line character).

ErrorEdit

The Error output is used to divert error specific messages to the console. To a novice user this may seem fairly pointless, as this achieves the same as Output (as above). If you decide to write an application that runs another application (for example a scheduler), you may wish to monitor the output of that program - more specifically, you may only wish to be notified only of the errors that occur. If you coded your program to write to the Console.Error stream whenever an error occurred, you can tell your scheduler program to monitor this stream, and feedback any information that is sent to it. Instead of the Console appearing with the Error messages, your program may wish to log these to a file.

You may wish to revisit this after studying Streams and after learning about the Process class.

Command line argumentsEdit

Command line arguments are values that are passed to a console program before execution. For example, the Windows command prompt includes a copy command that takes two command line arguments. The first argument is the original file and the second is the location or name for the new copy. Custom console applications can have arguments as well. c sharp is object based programming language. .net framework is a Microsoft programming language is used to create web application,console application, mobile application.

using Sys
{
   public static void Main(string[] args)
       Console.WriteLine("Last Name: " + args[1]);
       Console.Read();
   }
}

If the above code is compiled to a program called username.exe, it can be executed from the command line using two arguments, e.g. "Bill" and "Gates":

C:\>username.exe Bill Gates

Notice how the Main() method above has a string array parameter. The program assumes that there will be two arguments. That assumption makes the program unsafe. If it is run without the expected number of command line arguments, it will crash when it attempts to access the missing argument. To make the program more robust, we can check to see if the user entered all the required arguments.

using System;

public class Test
{
   public static void Main(string[] args)
   {
       if(args.Length >= 1)
           Console.WriteLine(args[0]);
       if(args.Length >= 2)
           Console.WriteLine(args[1]);
   }
}

Try running the program with only entering your first name or no name at all. The args.Length property returns the total number of arguments. If no arguments are given, it will return zero.

You are also able to group a single argument together by using the quote marks (""). This is particularly useful if you are expecting many parameters, but there is a requirement for including spaces (e.g. file locations, file names, full names etc.)

using System;
 
class Test
{
   public static void Main(string[] args)
   {
      for (int index = 0; index < args.Length; index++)
      {
         Console.WriteLine((index + 1) + ": " + args[index]);
      }
   }
}
C:\> Test.exe Separate words "grouped together"
1: Separate
2: words
3: grouped together

Formatted outputEdit

Console.Write() and Console.WriteLine() allow you to output a text string, but also allows writing a string with variable substitution.

These two functions normally have a string as the first parameter. When additional objects are added, either as parameters or as an array, the function will scan the string to substitute objects in place of tokens.

For example:

{
  int i = 10;
  Console.WriteLine("i = {0}", i);
}

The {0} is identified by braces, and refers to the parameter index that needs to be substituted. You may also find a format specifier within the braces, which is preceded by a colon and the specifier in question (e.g. {0:G}).

Rounding number exampleEdit

This is a small example that rounds a number to a string. It is an augmentation for the Math class of C#. The result of the Round method has to be rounded to a string, as significant figures may be trailing zeros that would disappear, if a number format would be used. Here is the code and its call. You are invited to write a shorter version that gives the same result, or to correct errors!

The constant class contains repeating constants that should exist only once in the code so that to avoid inadvertant changes. (If the one constant is changed inadvertantly, it is most likely to be seen, as it is used at several locations.)

using System;
 
namespace ConsoleApplicationCommons
{
    class Common
    {
        /// <summary>Constant of comma or decimal point in German</summary>
        public const char COMMA = ',';
        /// <summary>Dash or minus constant</summary>
        public const char DASH = '-';
        /// <summary>
        /// The exponent sign in a scientific number, or the capital letter E
        /// </summary>
        public const char EXPONENT = 'E';
        /// <summary>The full stop or period</summary>
        public const char PERIOD = '.';
        /// <summary>The zero string constant used at several places</summary>
        public const String ZERO = "0";
    } // class Common
}

The Math class is an enhancement to the <math.h> library and contains the rounding calculations.

using System;
using System.Globalization;
using System.IO;
using System.Text;
 
namespace ConsoleApplicationCommons
{
    /// <summary>
    /// Class for special mathematical calculations.
    /// ATTENTION: Should not depend on any other class except Java libraries!
    /// </summary>
    public class Maths
    {
        public static CultureInfo invC = CultureInfo.InvariantCulture;
        /// <summary>
        /// Value after which the language switches from scientific to double
        /// </summary>
        private const double E_TO_DOUBLE = 1E-4;
        /// <summary>
        /// Maximal digits after which Convert.ToString(…) becomes inaccurate.
        /// </summary>
        private const short MAX_CHARACTERS = 16;
        /// <summary>The string of zeros</summary>
        private static String strZeros = "000000000000000000000000000000000";
 
        /// <summary>
        /// Determines language-independently whether or not the character
        /// can be a decimal separator or not
        /// </summary>
        /// <param name="character">Character to be checked</param>
        /// <returns>
        /// true, if it can be a decimal separator in a language, and false
        /// otherwise.
        /// </returns>
        private static bool IsDecimalSeparator(char c)
        {
            return ((c == Common.COMMA) || (c == Common.PERIOD));
        }
 
        /// <summary>
        /// Determines how many zeros are to be appended after the decimal
        /// digits.
        /// </summary>
        /// <param name="separator">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="d">Rounded number</param>
        /// <param name="significantsAfter">
        /// Significant digits after decimal
        /// </param>
        /// <returns>Requested value</returns>
        private static short CalculateMissingSignificantZeros(char separator,
            double d,
            short significantsAfter)
        {
            short after = FindSignificantsAfterDecimal(separator, d);
 
            short zeros = (short)(significantsAfter
                - ((after == 0) ? 1 : after));
 
            return (short)((zeros >= 0) ? zeros : 0);
        }
 
        /// <summary>
        /// Finds the decimal position language-independently.
        /// </summary>
        /// <param name="value">
        /// Value to be searched for the decimal separator
        /// </param>
        /// <returns>The position of the decimal separator</returns>
        private static short FindDecimalSeparatorPosition(String value)
        {
            short separatorAt = (short)value.IndexOf(Common.COMMA);
 
            return (separatorAt > -1)
                ? separatorAt : (short)value.IndexOf(Common.PERIOD);
        }
 
        /// <summary>
        /// Calculates the number of significant digits (without the sign and
        /// the decimal separator).
        /// </summary>
        /// <param name="separator">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="d">Value where the digits are to be counted</param>
        /// <param name="significantsAfter">
        /// Number of decimal places after the separator
        /// </param>
        /// <returns>Number of significant digits</returns>
        private static short FindSignificantDigits(char separator,
            double d,
            short significantsAfter)
        {
            if (d == 0) return 0;
            else
            {
                String mantissa = FindMantissa(separator, 
                    Convert.ToString(d, invC));
 
                if (d == (long)d)
                {
                    mantissa = mantissa.Substring(0, mantissa.Length - 1);
                }
 
                mantissa = RetrieveDigits(mantissa);
                // Find the position of the first non-zero digit:
                short nonZeroAt = 0;
 
                for (; (nonZeroAt < mantissa.Length)
                        && (mantissa[nonZeroAt] == '0'); nonZeroAt++) ;
 
                return (short)mantissa.Substring(nonZeroAt).Length;
            }
        }
 
        /// <summary>
        /// Finds the significant digits after the decimal separator of a
        /// mantissa.
        /// </summary>
        /// <param name="separator">Language-specific decimal separator</param>
        /// <param name="d">Value to be scrutinised</param>
        /// <returns>Number of insignificant zeros after decimal separator.
        /// </returns>
        private static short FindSignificantsAfterDecimal(char separator,
            double d)
        {
            if (d == 0) return 1;
            else
            {
                String value = ConvertToString(d);
 
                short separatorAt = FindDecimalSeparatorPosition(value);
 
                if (separatorAt > -1) value = value.Substring(separatorAt + 1);
 
                short eAt = (short) value.IndexOf(Common.EXPONENT);
 
                if ((separatorAt == -1) && (eAt == -1)) return 0;
                else if (eAt > 0) value = value.Substring(0, eAt);
 
                long longValue = Convert.ToInt64(value, invC);
 
                if (longValue == 0) return 0;
                else if (Math.Abs(d) < 1)
                {
                    value = Convert.ToString(longValue, invC);
 
                    if (value.Length >= 15)
                    {
                        return (byte)Convert.ToString(longValue, invC).Length;
                    }
                    else return (byte)(value.Length);
                }
                else
                {
                    if (value.Length >= 15) return (byte)(value.Length - 1);
                    else return (byte)(value.Length);
                }
            }
        }
 
        /// <summary>
        /// Determines the number of significant digits after the decimal
        /// separator knowing the total number of significant digits and
        /// the number before the decimal separator.
        /// </summary>
        /// <param name="significantsBefore">
        /// Number of significant digits before separator
        /// </param>
        /// <param name="significantDigits">
        /// Number of all significant digits
        /// </param>
        /// <returns>
        /// Number of significant decimals after the separator
        /// </returns>
        private static short FindSignificantsAfterDecimal(
            short significantsBefore,
            short significantDigits)
        {
            short significantsAfter =
                (short)(significantDigits - significantsBefore);
 
            return (short)((significantsAfter > 0) ? significantsAfter : 0);
        }
 
        /// <summary>
        /// Determines the number of digits before the decimal point.
        /// </summary>
        /// <param name="separator">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="value">Value to be scrutinised</param>
        /// <returns>
        /// Number of digits before the decimal separator
        /// </returns>
        private static short FindSignificantsBeforeDecimal(char separator,
            double d)
        {
            String value = Convert.ToString(d, invC);
 
            // Return immediately, if result is clear: Special handling at
            // crossroads of floating point and exponential numbers:
            if ((d == 0) || (Math.Abs(d) >= E_TO_DOUBLE) && (Math.Abs(d) < 1))
            {
                return 0;
            }
            else if ((Math.Abs(d) > 0) && (Math.Abs(d) < E_TO_DOUBLE)) return 1;
            else
            {
                short significants = 0;
 
                for (short s = 0; s < value.Length; s++)
                {
                    if (IsDecimalSeparator(value[s])) break;
                    else if (value[s] != Common.DASH) significants++;
                }
 
                return significants;
            }
        }
 
        /// <summary>
        /// Returns the exponent part of the double number.
        /// </summary>
        /// <param name="d">Value of which the exponent is of interest</param>
        /// <returns>Exponent of the number or zero.</returns>
        private static short FindExponent(double d)
        {
            return short.Parse(FindExponent(Convert.ToString(d, invC)), invC);
        }
 
        /// <summary>
        /// Finds the exponent of a number.
        /// </summary>
        /// <param name="value">
        /// Value where an exponent is to be searched
        /// </param>
        /// <returns>Exponent, if it exists, or "0".</returns>
        private static String FindExponent(String value)
        {
            short eAt = (short)(value.IndexOf(Common.EXPONENT));
 
            if (eAt < 0) return Common.ZERO;
            else
            {
                return Convert.ToString
                    (short.Parse(value.Substring(eAt + 1)), invC);
            }
        }
 
        /// <summary>
        /// Finds the mantissa of a number.
        /// </summary>
        /// <param name="separator">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="value">Value where the mantissa is to be found</param>
        /// <returns>Mantissa of the number</returns>
        private static String FindMantissa(char separator,
            String value)
        {
            short eAt = (short)(value.IndexOf(Common.EXPONENT));
 
            if (eAt > -1) value = value.Substring(0, eAt);
 
            if (FindDecimalSeparatorPosition(value) == -1) value += ".0";
 
            return value;
        }
 
        /// <summary>
        /// Retrieves the digits of the value only
        /// </summary>
        /// <param name="d">Number</param>
        /// <returns>The digits only</returns>
        private static String RetrieveDigits(double d)
        {
            double dValue = d;
            short exponent = FindExponent(d);
            StringBuilder value = new StringBuilder();
 
            if (exponent == 0)
            {
                value.Append(dValue);
 
                if (value.Length >= MAX_CHARACTERS)
                {
                    value.Clear();
 
                    if (Math.Abs(dValue) < 1) value.Append("0");
 
                    // Determine the exponent for a scientific form:
                    exponent = 0;
 
                    while (((long)dValue != dValue) && (dValue < 1E11))
                    {
                        dValue *= 10;
                        exponent++;
                    }
 
                    value.Append((long)dValue);
 
                    while ((long)dValue != dValue)
                    {
                        dValue -= (long)dValue;
 
                        dValue *= 10;
 
                        value.Append((long)dValue);
                    }
                }
            }
            else
            {
                double multiplier = Math.Pow(10, -exponent);
 
                for (short s = 0; (s <= 16) && (exponent != 0); s++)
                {
                    dValue *= multiplier;
 
                    value.Append((long)dValue);
                    dValue -= (long)dValue;
                    exponent++;
                    multiplier = 10;
                }
            }
 
            if (value.Length >= MAX_CHARACTERS + 2)
                value.Length = MAX_CHARACTERS + 2;
 
            return RetrieveDigits(value.ToString());
        }
 
        /// <summary>
        /// Retrieves the digits of the value only
        /// </summary>
        /// <param name="number">Value to be scrutinised</param>
        /// <returns>The digits only</returns>
        private static String RetrieveDigits(String number)
        {
            // Strip off exponent part, if it exists:
            short eAt = (short)number.IndexOf(Common.EXPONENT);
 
            if (eAt > -1) number = number.Substring(0, eAt);
 
            return number.Replace(Convert.ToString(Common.DASH), "").Replace(
                Convert.ToString(Common.COMMA), "").Replace(
                Convert.ToString(Common.PERIOD), "");
        }
 
        /// <summary>
        /// Inserts the decimal separator at the right place
        /// </summary>
        /// <param name="dValue">Number</param>
        /// <param name="value">
        /// String variable, where the separator is to be added.
        /// </param>
        private static void InsertSeparator(double dValue, StringBuilder value)
        {
            short separatorAt = (short)Convert.ToString((long)dValue).Length;
 
            if (separatorAt < value.Length)
                value.Insert(separatorAt, Common.PERIOD);
        }
 
        /// <summary>
        /// Calculates the power of the base to the exponent without changing
        /// the least-significant digits of a number.
        /// </summary>
        /// <param name="basis"></param>
        /// <param name="exponent">basis to power of exponent</param>
        /// <returns></returns>
        public static double Power(int basis, short exponent)
        {
            return Power((short)basis, exponent);
        }
 
        /// <summary>
        /// Calculates the power of the base to the exponent without changing
        /// the least-significant digits of a number.
        /// </summary>
        /// <param name="basis"></param>
        /// <param name="exponent"></param>
        /// <returns>basis to power of exponent</returns>
        public static double Power(short basis, short exponent)
        {
            if (basis == 0) return (exponent != 0) ? 1 : 0;   
            else
            {
                if (exponent == 0) return 1;
                else
                {
                    // The Math method power does change the least significant
                    // digits after the decimal separator and is therefore
                    // useless.
                    long result = 1;
                    short s = 0;
 
                    if (exponent > 0)
                    {
                        for (; s < exponent; s++) result *= basis;
                    }
                    else if (exponent < 0)
                    {
                        for (s = exponent; s < 0; s++) result /= basis;
                    }
 
                    return result;
                }
            }
        }
 
        /// <summary>
        /// Rounds a number to the decimal places.
        /// </summary>
        /// <param name="d">Number to be rounded</param>
        /// <param name="separator">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="significantsAfter">
        /// Number of decimal places after the separator
        /// </param>
        /// <returns>Rounded number to the requested decimal places</returns>
        public static double Round(char separator,
            double d,
            short significantsAfter)
        {
            if (d == 0) return 0;
            else
            {
                double constant = Power(10, significantsAfter);
                short dsExponent = FindExponent(d);
 
                short exponent = dsExponent;
 
                double value = d*constant*Math.Pow(10, -exponent);
                String exponentSign = (exponent < 0)
                    ? Convert.ToString(Common.DASH) : "";
 
                if (exponent != 0)
                {
                    exponent = (short)Math.Abs(exponent);
 
                    value = Round(value);
                }
                else
                {
                    while (FindSignificantsBeforeDecimal(separator, value)
                        < significantsAfter)
                    {
                        constant *= 10;
                        value *= 10;
                    }
 
                    value = Round(value)/constant;
                }
 
                // Power method cannot be used, as the exponentiated number may
                // exceed the maximal long value.
                exponent -= (short)(Math.Sign(dsExponent)*
                    (FindSignificantDigits(separator, value, significantsAfter)
                    - 1));
 
                if (dsExponent != 0)
                {
                    String strValue = Convert.ToString(value, invC);
 
                    short separatorAt = FindDecimalSeparatorPosition(strValue);
 
                    if (separatorAt > -1)
                    {
                        strValue = strValue.Substring(0, separatorAt);
                    }
 
                    strValue += Common.EXPONENT + exponentSign
                        + Convert.ToString(exponent);
 
                    value = double.Parse(strValue, invC);
                }
 
                return value;
            }
        }
 
        /// <summary>
        /// Rounds a number according to mathematical rules.
        /// </summary>
        /// <param name="d">Number to be rounded</param>
        /// <returns>Rounded number</returns>
        public static double Round(double d)
        {
            return (long)(d + .5);
        }
 
        /// <summary>
        /// Converts a double value to a string such that it reflects the double
        /// format (without converting it to a scientific format by itself, as
        /// it is the case with Convert.ToString(double, invC)).
        /// </summary>
        /// <param name="d">Value to be converted</param>
        /// <returns>Same format value as a string</returns>
        public static String ConvertToString(double d)
        {
            double dValue = d;
            StringBuilder value = new StringBuilder();
 
            if (Math.Sign(dValue) == -1) value.Append(Common.DASH);
 
            if ((dValue > 1E-5) && (dValue < 1E-4))
            {
                value.Append("0");
 
                while ((long)dValue == 0)
                {
                    dValue *= 10;
 
                    if (dValue >= 1) break;
 
                    value.Append(Convert.ToString((long)dValue));
                }
            }
 
            short exponent = FindExponent(d);
 
            if (exponent != 0)
            {
                value.Append(RetrieveDigits(dValue));
                InsertSeparator(dValue, value);
                value.Append(Common.EXPONENT);
                value.Append(exponent);
            }
            else
            {
                value.Append(RetrieveDigits(dValue));
 
                InsertSeparator(dValue, value);
 
                if (value.Length > MAX_CHARACTERS + 3)
                {
                    value.Length = MAX_CHARACTERS + 3;
                }
            }
 
            return value.ToString();
        }
 
        /// <summary>
        /// Rounds to a fixed number of significant digits.
        /// </summary>
        /// <param name="d">Number to be rounded</param>
        /// <param name="significantDigits">
        /// Requested number of significant digits
        /// </param>
        /// <param name="separator">
        /// Language-specific decimal separator
        /// </param>
        /// <returns>Rounded number</returns>
        public static String RoundToString(char separator,
            double d,
            short significantDigits)
        {
            // Number of significants that *are* before the decimal separator:
            short significantsBefore =
                FindSignificantsBeforeDecimal(separator, d);
            // Number of decimals that *should* be after the decimal separator:
            short significantsAfter = FindSignificantsAfterDecimal(
                    significantsBefore, significantDigits);
            // Round to the specified number of digits after decimal separator:
            double rounded = Maths.Round(separator, d, significantsAfter);
 
            String exponent = FindExponent(Convert.ToString(rounded, invC));
            String mantissa = FindMantissa(separator, 
                            Convert.ToString(rounded, invC));
 
            double dMantissa = double.Parse(mantissa, invC);
            StringBuilder result = new StringBuilder(mantissa);
            // Determine the significant digits in this number:
            short significants = FindSignificantDigits(separator, dMantissa,
                significantsAfter);
            // Add lagging zeros, if necessary:
            if (significants <= significantDigits)
            {
                if (significantsAfter != 0)
                {
                    result.Append(strZeros.Substring(0,
                        CalculateMissingSignificantZeros(separator,
                            dMantissa, significantsAfter)));
                }
                else
                {
                    // Cut off the decimal separator & after decimal digits:
                    short decimalValue = (short) result.ToString().IndexOf(
                            Convert.ToString(separator));
 
                    if (decimalValue > -1) result.Length = decimalValue;
                }
            }
            else if (significantsBefore > significantDigits)
            {
                d /= Power(10, (short)(significantsBefore - significantDigits));
 
                d = Round(d);
 
                short digits = (short)(significantDigits + ((d < 0) ? 1 : 0));
 
                String strD = d.ToString().Substring(0, digits);
 
                result.Length = 0;
                result.Append(strD + strZeros.Substring(0,
                        significantsBefore - significantDigits));
            }
 
            if (short.Parse(exponent, invC) != 0)
            {
                result.Append(Common.EXPONENT + exponent);
            }
 
            return result.ToString();
        } // public static String RoundToString(…)
 
        /// <summary>
        /// Rounds to a fixed number of significant digits.
        /// </summary>
        /// <param name="separator">
        /// Language-specific decimal separator
        /// </param>
        /// <param name="significantDigits">
        /// Requested number of significant digits
        /// </param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static String RoundToString(char separator,
                float value,
                int significantDigits)
        {
            return RoundToString(separator, (double)value,
                (short)significantDigits);
        }
    }   // public class Maths
}

Extensive testing of a software is crucial for qualitative code. To say that the code is tested does not give much information. The question is what is tested. Not in this case, but often it is also important to know where (in which environment) it was tested, and how - i.e. the test succession. Here is the code used to test the Maths class.

using System;
using System.Collections.Generic;
 
namespace ConsoleApplicationCommons
{
    class TestCommon
    {
        /// <summary>
        /// Test for the common functionality
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            // Test rounding
            List<double> values = new List<double>();
 
            values.Add(0.0);
            AddValue(1.4012984643248202e-45, values);
            AddValue(1.999999757e-5, values);
            AddValue(1.999999757e-4, values);
            AddValue(1.999999757e-3, values);
            AddValue(0.000640589, values);
            AddValue(0.3396899998188019, values);
            AddValue(0.34, values);
            AddValue(7.07, values);
            AddValue(118.188, values);
            AddValue(118.2, values);
            AddValue(123.405009, values);
            AddValue(30.76994323730469, values);
            AddValue(130.76994323730469, values);
            AddValue(540, values);
            AddValue(12345, values);
            AddValue(123456, values);
            AddValue(540911, values);
            AddValue(9.223372036854776e56, values);
 
            const short SIGNIFICANTS = 5;
 
            foreach (double element in values)
            {
                Console.Out.WriteLine("Maths.Round('" + Common.PERIOD + "', "
                    + Convert.ToString(element, Maths.invC) + ", "
                    + SIGNIFICANTS + ") = " + Maths.RoundToString
                        (Common.PERIOD, element, SIGNIFICANTS));
            }
 
            Console.In.Read();
        }
 
        /// <summary>
        /// Method that adds a negative and a positive value
        /// </summary>
        /// <param name="d"></param>
        /// <param name="values"></param>
        private static void AddValue(double d, List<double> values)
        {
            values.Add(-d);
            values.Add(d);
        }
    } // class TestCommon
}

The results of your better code should comply with the result I got:

Maths.Round('.', 0, 5) = 0.00000
Maths.Round('.', -1.40129846432482E-45, 5) = -1.4012E-45
Maths.Round('.', 1.40129846432482E-45, 5) = 1.4013E-45
Maths.Round('.', -1.999999757E-05, 5) = -1.9999E-5
Maths.Round('.', 1.999999757E-05, 5) = 2.0000E-5
Maths.Round('.', -0.0001999999757, 5) = -0.00019999
Maths.Round('.', 0.0001999999757, 5) = 0.00020000
Maths.Round('.', -0.001999999757, 5) = -0.0019999
Maths.Round('.', 0.001999999757, 5) = 0.0020000
Maths.Round('.', -0.000640589, 5) = -0.00064058
Maths.Round('.', 0.000640589, 5) = 0.00064059
Maths.Round('.', -0.339689999818802, 5) = -0.33968
Maths.Round('.', 0.339689999818802, 5) = 0.33969
Maths.Round('.', -0.34, 5) = -0.33999
Maths.Round('.', 0.34, 5) = 0.34000
Maths.Round('.', -7.07, 5) = -7.0699
Maths.Round('.', 7.07, 5) = 7.0700
Maths.Round('.', -118.188, 5) = -118.18
Maths.Round('.', 118.188, 5) = 118.19
Maths.Round('.', -118.2, 5) = -118.19
Maths.Round('.', 118.2, 5) = 118.20
Maths.Round('.', -123.405009, 5) = -123.40
Maths.Round('.', 123.405009, 5) = 123.41
Maths.Round('.', -30.7699432373047, 5) = -30.769
Maths.Round('.', 30.7699432373047, 5) = 30.770
Maths.Round('.', -130.769943237305, 5) = -130.76
Maths.Round('.', 130.769943237305, 5) = 130.77
Maths.Round('.', -540, 5) = -539.99
Maths.Round('.', 540, 5) = 540.00
Maths.Round('.', -12345, 5) = -12344
Maths.Round('.', 12345, 5) = 12345
Maths.Round('.', -123456, 5) = -123450
Maths.Round('.', 123456, 5) = 123460
Maths.Round('.', -540911, 5) = -540900
Maths.Round('.', 540911, 5) = 540910
Maths.Round('.', -9.22337203685478E+56, 5) = -9.2233E56
Maths.Round('.', 9.22337203685478E+56, 5) = 9.2234E56

If you are interested in a comparison with C++, please compare it with the same example there. If you want to compare C# with Java, take a look at the rounding number example there.