none
why is "Main" in C# not a "public" static ????? RRS feed

  • Question

  •  

    Hi All,

     

    I am trying to understand why in C#  the entry point function

     

    Code Snippet

    static void Main(string[] args)

     

     

    is not explicitly declared as "public" . As the default access specifier for any method in a class is "private", the above declaration would make the entry point function "Main" as a private method.

     

    My question is , if the "Main" method is private how is the runtime going to invoke this static function ?? .  Please enlighten if I am missing something.

     

    Thanks a million in advance

     

    Cheers

    Kodez

    Wednesday, May 21, 2008 7:55 PM

Answers

  • The CLR doesn't actually mind if your method is private or public.  It doesn't invoke it through the use of normal C# code.  Here's what the native call stack looks like if you're interested:

     

    00000000`0014ea10 00000642`7f67d4a2 0x642`80150142
    00000000`0014ea90 00000642`7f5108f5 mscorwks!CallDescrWorker+0x82
    00000000`0014eae0 00000642`7f522ff6 mscorwks!CallDescrWorkerWithHandler+0xe5
    00000000`0014eb80 00000642`7f49a94b mscorwks!MethodDesc::CallDescr+0x306
    00000000`0014edb0 00000642`7f474ae4 mscorwks!ClassLoader::RunMain+0x23f
    00000000`0014f010 00000642`7f5efb1a mscorwks!Assembly::ExecuteMainMethod+0xbc
    00000000`0014f300 00000642`7f467d97 mscorwks!SystemDomain::ExecuteMainMethod+0x492
    00000000`0014f8d0 00000642`7f482c24 mscorwks!ExecuteEXE+0x47

    The address at the top is your Main method.

    Wednesday, May 21, 2008 8:43 PM
  • It can be public if you want; but that would mean any other application could reference it without reflection.

     

    That's what the runtime does; just start looking for static methods named "Main" with various signatures and then invokes the first one it finds.  Likely something like this:

    Code Snippet

    foreach(Type type in assembly.GetTypes())

    {

        foreach(MethodInfo methodInfo in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))

        {

            if (methodInfo.Name == "Main" /*TODO: && methodInfo.Parameters is valid*/)

            {

                methodInfo.Invoke(null, new object[0]);

            }

        }

    }

     

     

     

    Wednesday, May 21, 2008 8:47 PM
    Moderator

All replies

  • The CLR doesn't actually mind if your method is private or public.  It doesn't invoke it through the use of normal C# code.  Here's what the native call stack looks like if you're interested:

     

    00000000`0014ea10 00000642`7f67d4a2 0x642`80150142
    00000000`0014ea90 00000642`7f5108f5 mscorwks!CallDescrWorker+0x82
    00000000`0014eae0 00000642`7f522ff6 mscorwks!CallDescrWorkerWithHandler+0xe5
    00000000`0014eb80 00000642`7f49a94b mscorwks!MethodDesc::CallDescr+0x306
    00000000`0014edb0 00000642`7f474ae4 mscorwks!ClassLoader::RunMain+0x23f
    00000000`0014f010 00000642`7f5efb1a mscorwks!Assembly::ExecuteMainMethod+0xbc
    00000000`0014f300 00000642`7f467d97 mscorwks!SystemDomain::ExecuteMainMethod+0x492
    00000000`0014f8d0 00000642`7f482c24 mscorwks!ExecuteEXE+0x47

    The address at the top is your Main method.

    Wednesday, May 21, 2008 8:43 PM
  • It can be public if you want; but that would mean any other application could reference it without reflection.

     

    That's what the runtime does; just start looking for static methods named "Main" with various signatures and then invokes the first one it finds.  Likely something like this:

    Code Snippet

    foreach(Type type in assembly.GetTypes())

    {

        foreach(MethodInfo methodInfo in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))

        {

            if (methodInfo.Name == "Main" /*TODO: && methodInfo.Parameters is valid*/)

            {

                methodInfo.Invoke(null, new object[0]);

            }

        }

    }

     

     

     

    Wednesday, May 21, 2008 8:47 PM
    Moderator
  • Main should not be public since it is not suposed to be called by any other methods in your assemblies. It is only the CLR that should be able to call it when the application starts. The access specifiers does not apply to the CLR in the same way (if at all) as to your assemblies that are managed by the CLR.

     

    /Ruben

    RJJournal

     

    Wednesday, May 21, 2008 8:53 PM
  • That was some  interesting  stuff I learnt about the framework, thanks all.

     

    Wednesday, May 21, 2008 9:47 PM
  • Peter, the CLR doesn't invoke the first method called Main that it finds.  It invokes the one method (whether it's called Main or not matters for the C# compiler only) that is marked as the assembly's entry point.

     

    Here's the IL for the Main method that is the entry point:

    .method private hidebysig static void Main(string[] args) cil managed
    {
        .entrypoint
        .maxstack 8
        L_0000: nop 
        L_0001: ret 
    }
    

    And here's the IL for the Main method that is not the entry point:

    .method private hidebysig static void Main(string[] args) cil managed
    {
        .maxstack 8
        L_0000: nop 
        L_0001: ret 
    }
    

     

    If you have multiple static Main methods in various types in your code, the C# compiler will ask you to disambiguate them with the /main compiler switch (or the Startup Object combo box in the VS project settings).

     

    Thursday, May 22, 2008 7:57 AM
  • Cool

    MSDN just says it should be but leave out the reason.

    Friday, January 20, 2012 7:27 AM