创建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.ThreadException和AppDomain.CurrentDomain.UnhandledException的处理而不是更多地实现它或者我的所有项目都不尽相同。
答案 0 :(得分:14)
仅遵循设计准则,仅包含static
方法的类应标记为static
。可以找到更多信息here。
使Program
类不是静态没有问题,唯一需要的是static Main
方法作为入口点,正如您已经注意到的那样。您可以将实例方法添加到Program
类,实例化它并像其他任何类一样使用。然而,这不是一个明确的方法,因为这违反了Single Responsibility Principle。 Program
的责任是为应用程序提供一个入口点,因此它不应该做更多的事情。对于此任务,它只需要一个名为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.ThreadException
和AppDomain.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调用它,并且可以在所有程序中重复使用。