My question is, why is the Program
class declared as static
?
As you note, it doesn't have to be. In fact, in my version of Visual Studio (Visual Studio 2015 Enterprise Update 1) the default program for "Console Application" is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
}
}
}
But wait, why is Main
static again?
This answer does an excellent job of explaining why Main
must be static. In short, the answer states that Main
must be static because the alternative is that the CLR would have to call the constructor on Program
in order to call Program.Main
. But think about it, nothing happens before the entry point so no such constructor can be called!
The reason for the question is that I thought it could be nice to have Program
inherit from a base class that would implement handling of Application.ThreadException
and AppDomain.CurrentDomain.UnhandledException
instead of implementing it more or less the same for all of my projects.
This is a really good idea; DRY is one of my favorite programming principles. However, to do it in the way you were thinking, Program
would need to derive from a base object of type, say, ProgramBase
and call some sort of protected method. Something like this perhaps?
internal class Program : ProgramBase
{
static void Main(string[] args)
{
// ERROR: "an object reference is required for the non-static
// field, method, or property ProgramBase.MainWrapper();"
MainWrapper();
}
protected override void DoMain()
{
// do something
}
}
internal abstract class ProgramBase
{
protected void MainWrapper()
{
try
{
// do some stuff
DoMain();
}
catch(...)
{
// handle some errors
}
}
protected abstract void DoMain();
}
The problem arises that to solve the problem with inheritance, Program.Main()
must call some sort of non-static method.
OK, now lets solve the problem a different way. Let's create an ApplicationBase
abstract class for applications of different types to derive from.
class Program
{
static void Main(string[] args)
{
var myApp = new MyApplication();
myApp.RunApp();
}
}
public class MyApplication : ApplicationBase
{
protected override void DoRunApp()
{
// do my stuff
}
}
public abstract class ApplicationBase
{
public void RunApp()
{
try
{
// create AppDomain, or some other construction stuff
// do some stuff
DoRunApp();
}
catch(...)
{
// handle some errors
}
catch(...)
{
// handle some other errors
}
}
protected abstract void DoRunApp();
}
NOW we're getting somewhere. Depending on what you are creating in your setup/creation phase, your DoRunApp()
signature may change but this sort of template should accomplish what you're looking for.
Thanks for reading.