【问题标题】:Why is the entry point allowed to be private? [duplicate]为什么允许入口点是私有的? [复制]
【发布时间】:2012-03-18 18:15:14
【问题描述】:

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

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

【问题讨论】:

  • private 方法不能被调用?
  • 好吧,如果我的代码正在解释您的代码,我是否必须遵循 C# 的规则?不,我可以为所欲为。
  • @delnan 那你怎么调用私有方法呢?
  • @Marlon 我就这么称呼它。当然,类外的大多数代码都不能轻易调用它(尽管仍然有反射),但是当然可以调用私有方法。否则它们将毫无用处。
  • @delnan 这不是我问题的重点吗?如果该方法是私有的,则意味着它只能在我的类中调用。那么如何调用这个方法是我的问题。

标签: c# .net


【解决方案1】:

来自 bytes.com 上的 Jon Skeet:

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

Source

另外,there's another question 已经在这里讨论了这个主题。

【讨论】:

  • 谢谢。我搜索的时候没有看到那个主题。这就解释了。
【解决方案2】:

MSDN 之后,Main 方法不应公开:

Main 在类或结构中声明。 Main 必须是静态的,并且 不应公开。 (在前面的示例中,它接收默认访问私有。)封闭的类或结构不是 必须是静态的。

【讨论】:

  • 我认为它没有理由 公开 - 如果它 公开,则允许其他程序调用它,这可以是有时非常有用。这看起来像是 MSDN 给我的一个不好的建议 :(
  • 这根本没有解释原因,只是重复了部分问题。
  • @MarcinJuraszek, "must"/"should"/"should not" 可能根据faqs.org/rfcs/rfc2119.html 使用:"SHOULD NOT ...表示在特定情况下可能存在正当理由,当特定的行为是可以接受的,甚至是有用的……”。基本上不推荐,但没关系,不像“不得”。
【解决方案3】:

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

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

粗体部分记录了 CLR 对 EntryPointToken 所做的工作。 C# 编译器可以根据需要验证可访问性,但不能。

【讨论】:

  • 我不明白“无论其封闭类型声明的声明可访问性如何”是什么意思。你能解释一下这是什么意思吗?
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    .Net 中的访问修饰符是(非常强大的)建议。您可以使用反射调用任何方法或访问任何属性/字段。考虑这样的代码,它的行为有点像 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());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-01
      • 1970-01-01
      • 2014-03-01
      • 2011-10-09
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多