为什么类“Program”声明为静态?

时间:2013-09-30 10:53:05

标签: c# winforms static

创建WinForm应用时,您会在Program文件中获得自动生成的Program.cs类模板。

看起来像这样:

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());
    }
}

我的问题是,为什么Program类声明为static? 如果我删除static声明,它仍然可以正常工作。

问题的原因是我认为让Program从基类继承来实现Application.ThreadExceptionAppDomain.CurrentDomain.UnhandledException的处理而不是更多地实现它或者我的所有项目都不尽相同。

4 个答案:

答案 0 :(得分:14)

仅遵循设计准则,仅包含static方法的类应标记为static。可以找到更多信息here

使Program类不是静态没有问题,唯一需要的是static Main方法作为入口点,正如您已经注意到的那样。您可以将实例方法添加到Program类,实例化它并像其他任何类一样使用。然而,这不是一个明确的方法,因为这违反了Single Responsibility PrincipleProgram的责任是为应用程序提供一个入口点,因此它不应该做更多的事情。对于此任务,它只需要一个名为static的{​​{1}}方法。由于它仅包含Main方法,因此应将其标记为static以符合 C#编码指南。

一般来说,知道一个类是static很方便,所以你乍一看它只包含static个方法。这是表达如何使用类的一种非常易读的方式。在这个示例中,它不是非常重要,因为没有人明确使用static,但为了严格,它应该是Program

答案 1 :(得分:5)

避免过度思考。此代码刚出自项目模板,预先在C:\ Program Files(x86)\ Microsoft Visual Studio 11.0 \ Common7 \ IDE \ ProjectTemplates \ CSharp \ Windows \ 1033 \ WindowsApplication \ Program.cs

中实现

没有什么可以阻止您修改代码,如果您喜欢它,那么删除 static 关键字是完全合理的。它有一个逻辑,你毕竟只有一个程序,因此声明静态是有意义的。但是将它与Console模式应用程序的项目模板进行比较,它还声明了一个Program类但没有使它成为静态。对于控制台应用来说,使该类不是静态的,根本没有任何意义。

修改项目模板代码肯定还有其他充分的理由。例如,它将Surface派生类的Dispose()方法放在Designer.cs文件中。对它来说不是一个好地方,“永远不会修改设计器生成的代码”规则确实让Winforms程序员陷入瘫痪。将该方法移动到Form.cs文件中然后修改它就可以了。

这仅仅是“最有可能落入成功的关键”代码。毫不犹豫地改变它。

答案 2 :(得分:5)

  

我的问题是,为什么Program类声明为static

正如您所指出的,它并非必须如此。事实上,在我的Visual Studio版本(Visual Studio 2015企业更新1)中,控制台应用程序的默认程序为#34;是

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)
        {
        }
    }
}

但是等一下,为什么Main再次静止?

This answer能够很好地解释为什么Main必须是静态的。简而言之,答案指出Main必须是静态的,因为替代方案是CLR必须调用Program上的构造函数才能调用Program.Main。但想想看,在入口点之前没有任何事情发生,所以不能调用这样的构造函数!

  

问题的原因是我认为让Program从基类继承来实现Application.ThreadExceptionAppDomain.CurrentDomain.UnhandledException的处理而不是更多地实现它或者我的所有项目都不尽相同。

这是一个非常好的主意; DRY是我最喜欢的编程原则之一。但是,要按照您的思维方式执行此操作,Program需要从类型的基础对象派生,例如ProgramBase并调用某种受保护的方法。这样的事可能呢?

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();
}

问题出现了,要解决继承问题,Program.Main()必须调用某种非静态方法。

好的,现在让我们以不同的方式解决问题。让我们为不同类型的应用程序创建一个ApplicationBase抽象类来派生。

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();
}

现在我们到了某个地方。根据您在设置/创建阶段创建的内容,DoRunApp()签名可能会发生变化,但此类模板应该可以完成您正在寻找的内容。

感谢阅读。

答案 3 :(得分:1)

它是静态的原因是,因为它只有静态方法而没有别的。 如果您现在要添加接口,基类和非静态方法/属性/成员,则必须创建该类的实例以使用它们(由于static class而禁止)。哪个仍然很好,甚至可以在静态Main方法中完成,但它可能会误导或不是该类的预期目的。我将创建一个MyApplication类,在静态Main中实例化并从那里创建我的Form。

关于您的异常处理程序。您仍然可以创建一个为您执行此操作的管理器类,您可以从Main调用它,并且可以在所有程序中重复使用。