What would be the minimal boilerplate code for a C# console application entry-point that would make it a well-behaved citizen?
When anyone goes out to create a Console Application project using Visual Studio (up to 2008 at the time of writing), you are presented with a boilerplate Program.cs
that looks like this:
class Program
{
static void Main(string[] args)
{
}
}
There are, however, a few things that everyone needs to do to make a console application a minimally good citizen. For example, if an exception occurs, then write out a clean message to standard error (Console.Error) and not standard output (Console.Out). Likewise, set the error code to a non-zero value in the event of some error so that calling processes can detect failures.
What would be the minimal boilerplate code for a C# console application entry-point that would make it a well-behaved citizen? What would you add or change to the following?
using System;
using System.Diagnostics;
using System.Linq;
static class Program
{
static void Run(string[] args)
{
// TODO Replace line-echoing sample with actual application code
string line;
while ((line = Console.ReadLine()) != null)
Console.WriteLine(line);
}
static int Main(string[] args)
{
// TODO Use a more robust arguments parser
if (args.Any(arg => arg.Equals("/v") || arg.Equals("-v"))) // verbose?
Trace.Listeners.Add(new ConsoleTraceListener(true));
try
{
Run(args);
return Environment.ExitCode;
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
Trace.TraceError(e.ToString());
return Environment.ExitCode != 0
? Environment.ExitCode : 100;
}
}
}
What this boilerplate achieves:
- If an exception is thrown:
- a clean message is printed to standard error
- the full details are traced
- the exit code is set to an arbitrary non-zero value (100) unless already set
- Tracing can be turned on dynamically via a verbose switch
- Tracing is sent to standard error to not interfere the real output
- On successful completion, the exit code reflects the last Environment.ExitCode value, which is usually zero but can be changed by downstream code
Program
class is static
Non-goals of this question:
- Identify command-line arguments handling code or library
- Identify an external logging or tracing library