为什么入口点被允许是私人的

本文关键字:入口 为什么 | 更新日期: 2023-09-27 18:28:07

这实际上是如何工作的?我以为Main应该被"调用"。但是,如果它被标记为私有,那怎么可能呢?

public class Program
{
    private static void Main()
    {
    }
}

为什么入口点被允许是私人的

来自bytes.com上的Jon Skeet:

基本上,主方法的执行是由特殊代码启动的在CLR内(或可能驱动CLR启动的代码)不需要遵守同样的规则。

此外,还有一个问题已经涵盖了这个主题。

在MSDN之后,Main方法不应该是公共的:

Main是在类或结构内部声明的。Main必须是静态的,并且它不应该是公共的。(在前面的示例中,它接收private的默认访问权限。)封闭类或结构不是要求是静态的。

这是一个语言实现细节,CLR只是从程序集标头中读取EntryPointToken值,并不对具有该令牌的方法执行可访问性检查。底层调用是_AppDomain.ExecuteAssembly()。因此,我们需要转向C#语言规范,第3.1节明确提到了可访问性规则:

在C#中,每个方法都必须定义为类或结构的成员。通常,一个方法的声明可访问性(§3.5.1)由其声明中指定的访问修饰符(§10.3.5)决定,类似地,一个类型的声明可存取性由其声明所指定的访问修饰符决定。为了使给定类型的给定方法可调用,类型和成员都必须是可访问的但是,应用程序入口点是一种特殊情况。具体地说,执行环境可以访问应用程序的入口点,而不管其声明的可访问性如何,也不管其封闭类型声明的声明可访问性是什么

粗体部分记录CLR对EntryPointToken所做的操作。如果愿意,C#编译器可以验证可访问性,但不能。

执行代码时,CLR会执行Main方法。CLR编译器会搜索该Main方法。即使你用小写字母表示main,它也不会被调用。

.Net中的Acces修饰符是(非常强烈的)建议。您可以使用反射调用任何方法或访问任何属性/字段。考虑一下这样的代码,它的行为有点像main被调用时实际发生的事情。

public class EntryPointAttribute : System.Attribute
{
    public string EntryPoint { get; private set; }
    public EntryPointAttribute(string entryPoint) { this.EntryPoint = entryPoint; }
}
public static class EntryPointProcessor
{
    public static void Process(object theObject)
    {
        Type t = theObject.GetType();
        var ep = t.GetCustomAttributes(typeof(EntryPointAttribute), true).FirstOrDefault();
        string entryPointName = ((EntryPointAttribute)ep).EntryPoint;
        MethodInfo mi = t.GetMethod(entryPointName, BindingFlags.Static | BindingFlags.NonPublic);
        mi.Invoke(null, new object[0] { });
    }
}
[EntryPoint("anentrypoint")]
public class entryPointClass
{
    private static void anentrypoint()
    {
        Console.WriteLine("in anentrypoint");
    }
}
class Program
{
    static void Main(string[] args)
    {
        EntryPointProcessor.Process(new entryPointClass());
    }
}