为什么Main()方法应该是静态的?

58

我尝试在C#中创建public void Main(),它提示说没有找到静态的void Main
那么什么是Main是静态的意思呢?我知道用public static void Main()可以正常工作。

为什么Main必须是static的呢?


关于Java有一个类似的问题,我认为那里的答案也适用于这里:https://dev59.com/W3VC5IYBdhLWcg3w51vy - Tudor
6
不清楚你的问题是因为你不理解“静态”在一般情况下的含义,还是特别针对于“Main”。 - Jon Skeet
6个回答

67

你需要一个程序的入口点。静态意味着你可以调用函数而不必实例化一个类的对象/实例。这有点像"先有鸡还是先有蛋"的问题......在进入程序之前,你不能实例化一个对象。

一个静态方法可以在不实例化对象的情况下被调用。因此,main() 需要是静态的才能允许它成为你的程序入口。

正如David所说,你只需在函数定义中添加关键字 static 即可更改它。值得研究静态(类)方法与实例方法之间的区别,了解这些差异有时会很有用。


37
“在程序内部执行之前,你不能实例化一个对象。”这是显然错误的。运行时会在执行 Main 方法之前实例化许多对象。您可以通过将静态构造函数放入包含 Main 方法的类中来手动触发此过程。抱歉,我意识到这个帖子已经超过一年了,但我认为这仍然相关。 - Konrad Rudolph
9
关键点是:该语言定义的不是实例化一个对象,然后调用它的Main函数,而是定义调用一个静态函数。它可能会有不同的工作方式,但现在没有。 - usr

19
只有静态的main方法才能完成这个任务,因为有一个约定规定了这种行为。没有其他原因。
看一下C#语言规范

Application startup occurs when the execution environment calls a designated method, which is referred to as the application's entry point. This entry point method is always named Main, and shall have one of the following signatures:

     static void Main() {…}  
     static void Main(string[] args) {…}  
     static int Main() {…}  
     static int Main(string[] args) {…}

As shown, the entry point can optionally return an int value. This return value is used in application termination (§10.2).

注意:以上引用自第4版,现已标记为“历史”。当前版本的措辞不同。

除此之外,名称Main可以更改为其他名称。在这种情况下,必须添加编译器选项,告诉C#编译器将不同的方法标记为程序的入口点。


9
你的回答很好地解释了什么是静态方法。你还解释了主方法是程序的入口点。但是问题提问者已经知道这一点。他想知道为什么必须使用静态方法。我的回答是没有根本的宇宙原因。语言设计者选择了这种方式。可能这受到其他语言如C、C++和Java的影响。 - Leonardo Cruz
2
我看你没有理解我的话!这是关于设计决策的问题。算了吧。 - Leonardo Cruz
4
语言设计者本可以决定创建 Program 的一个实例并在其上调用 Main 方法。我认为两个答案都是正确的,这是一个设计决策,因为他们考虑了你在回答中提到的内容。我的看法是这样的。 - BlackBear
5
这是(唯一的!)正确答案。其他答案都是相当错误的,原因在 Programmers.SE 上更详细的讨论 中有强调。/cc @ThomasClayson。 - Konrad Rudolph

6

类中有两种方法类型:

  1. 非静态方法
  2. 静态方法

这些方法可以通过类或对象来调用。静态方法可以直接通过类名调用,而非静态方法则需要先创建一个类的实例,然后通过该实例来调用方法。
// Example of static and non-static methods and how to call
namespace TestStaticVoidMain
{
    class Program
    {
        Static Void Main(string[] args)
        {
           // Instantiate or create object of the non-static method:
            Exam ob = new Exam();
            // Call the instance:
            ob.Test1();

            // Directly the call the static method by its class:
            Exam.Test2();

            Console.ReadKey();
        }
    }
    class Exam
    {
        public void Test1()
        {
            Console.WriteLine("This is a non-static method");
        }

        public static void Test2()
        {
            Console.WriteLine("This is a static method");
        }
    }
}

1. 静态方法:

调用静态方法(函数)时,我们不需要实例化或创建该方法的对象。我们不能使用new关键字,因为当类被加载和编译时,static关键字默认实例化或创建该类方法的对象,所以我们直接调用一个静态方法。

关于static void Main(string[] args),我们已经讨论了static。剩下的是void Main(string[] args)void是一种不返回任何值的数据类型。Main()是C#程序执行的标准入口点。可选参数string[] args接收程序运行时带有的可选“命令行”参数。

2. 非静态方法:

要调用非静态方法,我们必须实例化或创建该类方法的对象,使用关键字new来调用类的方法(函数)。

如果一个名为Test的类有一个名为show()非静态方法,那么它将如何调用一个实例:

// to call non-static method
Test ob=new Test();
ob.show();

清晰的例子。帮助我理解了这个问题,并且与其他答案相比,还告诉了我如何使用它。 - undefined

1
概念上,一个框架可以指定不使用特定的静态方法来运行程序,而是构造某个特定类的默认实例并在其中运行某个特定方法。如果有一个框架通过将静态方法作为编译器初始化的单例实例的实例成员来实现静态方法,这种方法可能是完全合理的,因为无论如何,框架都必须在调用主函数之前生成一个新的对象实例。
但是,如果调用静态方法比构造新的对象实例并在其中调用方法更容易,那么要求框架使用更昂贵的方法并没有太多好处。任何想要使用后一种方法的代码都可以自由地使用:
public static void Main( [[params]] )
{
  var mainObject = new MainObject();
  mainObject.Main( [[params]] );
}

为系统包含自己的静态方法可能带来一些潜在的好处,该方法大致如下:

public static void SysMain( [[params]] )
{
  using (Application app = new UserApp( [[params]] )) // UserApp derives from Application
  {
    app.Start(); // Virtual method
    app.AllowNext(); // Base method--see text
    app.Run(); // Abstract method
  }
}

在这里,app.AllowNext() 是一个方法,用于与在基本上同时启动的其他应用程序实例协调,以确保重复尝试在后台启动应用程序的Start调用严格按顺序处理。但如果没有这样一个协调方案,实际上要求框架在运行应用程序之前构造应用程序对象并没有太多好处。这种成本不会很大,但是如果没有任何潜在可识别的好处,那么接受甚至微不足道的成本也没有太多意义。


0
在应用程序启动时,当该类的对象未创建时,必须调用 Main 方法以开始程序执行。Main 有时被称为应用程序的入口点。将 Main 声明为静态允许执行环境在不创建类实例的情况下调用 Main。通常使用以下标题声明 Main 方法:
static void Main(){..}

但也可以使用标题声明:

static void Main(string[] args){..}

你可以声明带有返回类型 int 的 Main(而不是 void)—如果一个应用程序由另一个应用程序执行并需要向该其他应用程序返回成功或失败的指示,则这可能很有用。


-1

主函数应该是静态的,这样它会首先加载并成为程序的入口点,因此主函数的静态性非常重要。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接