'Why is the class "Program" declared as static?

When you create a WinForm App, you get an automatically generated template of Program class in the Program.cs file.

Which looks something like this:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

My question is, why is the Program class declared as static?
If I remove the static declaration it still works fine.

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.



Solution 1:[1]

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 Programinherit 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.

Solution 2:[2]

Avoid over-thinking this. This code just comes out of the project template, pre-cooked in C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ProjectTemplates\CSharp\Windows\1033\WindowsApplication\Program.cs

There's nothing to stop you from modifying that code, removing the static keyword is entirely reasonable if that's the way you prefer it. There is a bit of logic to it, you after all have only one program so declaring it static does make sense. But compare it to the project template for a Console mode app, It also declares a Program class but didn't make it static. It doesn't make extra sense at all to make that class not static for a console app.

There are certainly other good reasons to modify the project template code. It for example puts the Dispose() method for a Form derived class in the Designer.cs file. Not a great place for it, the "never modify designer generated code" rule does get Winforms programmers paralyzed. Moving that method into the Form.cs file and then modifying it is just fine.

This is merely "most likely to fall in the pit of success" code. Never hesitate to change it.

Solution 3:[3]

The reason for it to be static is, because it only has static methods and nothing else. If you would now add interfaces, base classes and non static methods/properties/members you would have to create an instance of that class to use them (which is forbidden because of the static class). Which is still fine, and could even be done in the static Main method, but it could be misleading or is not the intended purpose of that class. I would create a MyApplication class anway, instance it in the static Main and create my Form from there.

Regarding your Exception handlers. You can still create a manager class that does that for you, which you just call from your Main and can be reused in all your programs.

Solution 4:[4]

There is only one instance of the main method in memory and there is one entry point for each C# application.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 Hans Passant
Solution 3
Solution 4 Salar Afshar