Why is Main method private?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In C#, the Main method can be private because the runtime does not use normal access modifier rules to find and invoke it. The CLR (Common Language Runtime) locates Main by searching for a static method named Main with the correct signature, regardless of its access level. Making Main private prevents other classes from calling it directly, which is appropriate because it is an entry point, not a reusable API. In Java, main must be public because the JVM specification requires it.
C#: Main Can Be Private
The C# compiler and CLR find Main by its name and signature, not by its accessibility. The access modifier has no effect on whether the program starts — the runtime bypasses access checks for the entry point.
Why Private Makes Sense
Making Main private prevents accidental re-invocation from other parts of the codebase.
Java: main Must Be Public
The JVM specification requires main to be public static void main(String[]). Unlike C#'s CLR, the JVM respects access modifiers when searching for the entry point.
C# Valid Main Signatures
C# Top-Level Statements (C# 9+)
In C# 9+, you can skip Main entirely:
The compiler-generated Main is private by default — further evidence that the runtime does not require public.
Multiple Main Methods
If multiple classes define Main, the compiler requires you to specify which one to use:
Or from the command line:
Comparison Across Languages
| Language | Entry Point | Access Modifier | Why |
| C# | static Main() | Any (private OK) | CLR ignores access modifiers for entry point |
| Java | static main() | Must be public | JVM spec requires public |
| Kotlin | fun main() | Top-level function | No class needed, no modifier |
| C/C++ | int main() | N/A (no access modifiers at file scope) | Linker finds symbol by name |
| Python | No special entry | N/A | Script runs top to bottom |
| Go | func main() | Exported by convention | Must be in package main |
Common Pitfalls
- Assuming
Mainmust bepublicin C#: The CLR does not require any specific access modifier. MakingMainpublic is convention, not requirement. Private is equally valid and arguably better practice for preventing accidental invocation. - Trying private
mainin Java: The JVM will throwError: Main method not found in classat runtime. Java strictly enforcespublic static void main(String[] args). Evenprotectedor package-private will not work. - Multiple
Mainmethods without specifying startup object: If multiple classes in a C# project defineMain, the build fails withCS0017: Program has more than one entry point defined. Set<StartupObject>in the project file. - Confusing entry point discovery with reflection: The runtime's ability to call a private
Mainis not the same as reflection. It is a special runtime behavior for application startup only. Private methods are still inaccessible to other code through normal compilation. - Thinking
Mainaccess modifier affects security: MakingMainprivate does not provide meaningful security. It prevents source-level calls from other classes, but reflection can always invoke private methods. The primary benefit is API cleanliness.
Summary
- C#
Maincan beprivatebecause the CLR finds the entry point by name and signature, ignoring access modifiers - Java
mainmust bepublicbecause the JVM specification requires it - Private
Mainprevents other classes from accidentally calling the entry point directly - C# 9+ top-level statements generate a private
Mainautomatically - Valid C#
Mainsignatures includevoid,int,Task, andTask<int>, with or withoutstring[] args - The access modifier choice is about API design, not security or runtime behavior

