|
1 | 1 | --- |
2 | 2 | title: "General structure of a C# program" |
3 | 3 | description: Learn how C# programs are structured, including the choice between file-based and project-based apps, top-level statements and Main method entry points, and the building blocks that make up every program. |
4 | | -ms.date: 03/04/2026 |
| 4 | +ms.date: 03/11/2026 |
5 | 5 | ai-usage: ai-assisted |
6 | 6 | helpviewer_keywords: |
7 | 7 | - "C# language, program structure" |
8 | 8 | --- |
9 | 9 | # General structure of a C# program |
10 | 10 |
|
11 | | -You build C# programs from these core building blocks: namespaces organize your types, types (classes, structs, interfaces, enums, and delegates) define behavior and data, and statements and expressions perform work at run time. The way you structure the entry point - where your program starts running - depends on which application style you choose. |
| 11 | +> [!TIP] |
| 12 | +> **New to developing software?** Start with the [Get started](../../tour-of-csharp/tutorials/index.md) tutorials first. They walk you through writing your first C# programs before you learn about program structure. |
| 13 | +> |
| 14 | +> **Experienced in another language?** You might want to skim the [Get started](../../tour-of-csharp/tutorials/index.md) section for C#-specific syntax, then come back here. |
12 | 15 |
|
13 | | -The following example shows a modern C# program that uses [namespaces](namespaces.md), [top-level statements](top-level-statements.md), and typical C# features: |
14 | | - |
15 | | -:::code language="csharp" source="snippets/toplevel-structure/Program.cs"::: |
16 | | - |
17 | | -This example uses *top-level statements* for the program's entry point. Only one file in a project can have top-level statements, and the entry point is the first line of program text in that file. File-scoped namespaces (the `namespace YourNamespace;` syntax) reduce nesting by applying the namespace to the entire file. |
| 16 | +You build C# programs from these core building blocks: namespaces organize your types, types (classes, structs, interfaces, enums, and delegates) define behavior and data, and statements and expressions perform work at run time. The way you structure the entry point depends on which application style you choose. |
18 | 17 |
|
19 | 18 | ## Choosing your application style |
20 | 19 |
|
21 | 20 | When you create a C# program, make two independent choices about how to structure it: |
22 | 21 |
|
23 | | -1. **File-based or project-based?** A file-based app runs from a single `.cs` file with no project file. A project-based app uses a `.csproj` file and can span multiple source files. |
24 | | -1. **Top-level statements or `Main` method?** Top-level statements let you write executable code directly at the top of a file. A `Main` method wraps the entry point in an explicit static method. |
| 22 | +- **File-based or project-based?** |
| 23 | + - A file-based app runs from a single `.cs` file with no project file. |
| 24 | + - A project-based app uses a `.csproj` file and can span multiple source files. |
| 25 | +- **Top-level statements or `Main` method?** |
| 26 | + - Top-level statements let you write executable code directly at the top of a file. |
| 27 | + - A `Main` method wraps the entry point in an explicit static method. |
25 | 28 |
|
26 | 29 | Both project-based apps and file-based apps support either entry-point style. |
27 | 30 |
|
28 | 31 | ### File-based apps vs. project-based apps |
29 | 32 |
|
30 | | -Starting with C# 14 and .NET 10, *file-based apps* let you run a program contained in a single `*.cs` file without a project file. Store the following code in a file named `hello-world.cs` and run it with `dotnet run hello-world.cs`: |
| 33 | +Starting with C# 14 and .NET 10, *file-based apps* let you run a program contained in a single `*.cs` file without a project file. Store the following code in a file named `hello-world.cs` and run it with `dotnet run hello-world.cs` or `dotnet hello-world.cs`: |
31 | 34 |
|
32 | 35 | :::code language="csharp" source="./snippets/file-based-program/hello-world.cs"::: |
33 | 36 |
|
34 | | -The `#!` line enables Unix shells to run the file directly. On any Unix system, set the *execute* (`+x`) permission and run the file from the command line: |
| 37 | +> [!NOTE] |
| 38 | +> The `#!` line enables Unix shells to run the file directly. On any Unix system, set the *execute* (`+x`) permission and run the file from the command line: |
| 39 | +
|
| 40 | +File-based apps support all C# syntax and can use [preprocessor directives](../../language-reference/preprocessor-directives.md#file-based-apps) to configure the build system. Use file-based apps for small command-line utilities, prototypes, and experiments. A file-based app consists of a single file in a directory: |
35 | 41 |
|
36 | | -```bash |
37 | | -./hello-world.cs |
38 | 42 | ``` |
| 43 | +my-app/ |
| 44 | +└── hello-world.cs |
| 45 | +``` |
| 46 | + |
| 47 | +*Project-based apps* use a `.csproj` file and the [.NET CLI commands](../../../core/tools/index.md) `dotnet new`, `dotnet build`, and `dotnet run` workflow. Choose project-based apps when your program spans multiple files or needs fine-grained build configuration. A project-based app includes a project file alongside one or more source files: |
39 | 48 |
|
40 | | -File-based apps support all C# syntax and can use [preprocessor directives](../../language-reference/preprocessor-directives.md#file-based-apps) to configure the build system. Use file-based apps for small command-line utilities, prototypes, and experiments. |
| 49 | +``` |
| 50 | +my-app/ |
| 51 | +├── my-app.csproj |
| 52 | +├── Program.cs |
| 53 | +├── Models/ |
| 54 | +│ └── Person.cs |
| 55 | +└── Services/ |
| 56 | + └── GreetingService.cs |
| 57 | +``` |
41 | 58 |
|
42 | | -*Project-based apps* use a `.csproj` file and the [.NET CLI commands](../../../core/tools/index.md) `dotnet new`, `dotnet build`, and `dotnet run` workflow. Choose project-based apps when your program spans multiple files or needs fine-grained build configuration. |
| 59 | +If your file-based app grows, you can easily convert it to a project-based app. Run [`dotnet project convert`](../../../core/tools/dotnet-project-convert.md) to generate a project file from your existing source file. |
| 60 | + |
| 61 | +If you know your app needs multiple source files from the start, begin with a project-based app. You avoid the conversion step and can organize your code into separate files right away. |
43 | 62 |
|
44 | 63 | ### Top-level statements vs. `Main` method |
45 | 64 |
|
46 | | -[Top-level statements](top-level-statements.md) let you write executable code directly in one file, without wrapping it in a class and `Main` method. This style is the default when you create a new console app with `dotnet new console`. The first code example in this article uses this style. |
| 65 | +By using [top-level statements](top-level-statements.md), you can write executable code directly in one file without wrapping it in a class and `Main` method. This style is the default when you create a new console app with `dotnet new console`. The following example shows a modern C# program that uses [top-level statements](top-level-statements.md): |
| 66 | + |
| 67 | +:::code language="csharp" source="snippets/toplevel-structure/Program.cs"::: |
| 68 | + |
| 69 | +Only one file in a project can have top-level statements, and the entry point is the first line of program text in that file. As you build larger programs, you include more program elements. |
47 | 70 |
|
48 | 71 | You can also define an explicit static [`Main`](main-command-line.md) method as the program's entry point: |
49 | 72 |
|
50 | 73 | :::code language="csharp" source="snippets/structure/Program.cs"::: |
51 | 74 |
|
52 | | -Either entry-point style works with both file-based and project-based apps. Both styles support the same features. |
| 75 | +Both entry-point styles work with file-based and project-based apps. Both styles support the same features. |
53 | 76 |
|
54 | 77 | ## Building and running C# programs |
55 | 78 |
|
56 | | -C# is a *compiled* language. For project-based apps, use the [`dotnet build`](../../../core/tools/dotnet-build.md) command to compile source files into a binary package and [`dotnet run`](../../../core/tools/dotnet-run.md) to build and run in one step. The `dotnet` CLI, included in the .NET SDK, provides many [tools](../../../core/tools/index.md) to create, build, and manage C# projects. |
| 79 | +C# is a *compiled* language. For project-based apps, use the [`dotnet build`](../../../core/tools/dotnet-build.md) command to compile source files into a binary package. Use [`dotnet run`](../../../core/tools/dotnet-run.md) to build and run in one step. The `dotnet` CLI, included in the .NET SDK, provides many [tools](../../../core/tools/index.md) to create, build, and manage C# projects. |
57 | 80 |
|
58 | 81 | For file-based apps, `dotnet run hello-world.cs` compiles and runs the single file directly - no project file required. |
59 | 82 |
|
60 | 83 | ## Expressions and statements |
61 | 84 |
|
62 | | -C# programs use *expressions* and *statements*. |
| 85 | +If you followed the [Get started](../../tour-of-csharp/index.md) tutorials, you already wrote expressions and statements. Every line of code you typed was one or the other (or both). Now let's define those terms. |
63 | 86 |
|
64 | | -An *expression* produces a single value. The following are expressions: |
| 87 | +Expressions and statements are the fundamental building blocks of a C# program. An *expression* produces a value. A *statement* performs an action and typically ends in a semicolon. |
| 88 | + |
| 89 | +The following are expressions: |
65 | 90 |
|
66 | 91 | - `42` (literal value) |
67 | 92 | - `x + y` (arithmetic operation) |
68 | | -- `Math.Max(a, b)` (method call) |
| 93 | +- `Math.Max(a, b)` (method call that produces a value) |
69 | 94 | - `condition ? trueValue : falseValue` (conditional expression) |
70 | 95 | - `new Person("John")` (object creation) |
71 | 96 |
|
72 | 97 | A *statement* performs an action. Statements control program flow, declare variables, or invoke operations. The following are statements: |
73 | 98 |
|
74 | | -- `int x = 42;` (declaration statement) |
75 | | -- `Console.WriteLine("Hello");` (expression statement—wraps a method call expression) |
| 99 | +- `int x;` (declaration statement) |
| 100 | +- `int x = 42;` (declaration statement with initialization) |
| 101 | +- `Console.WriteLine("Hello");` (method call statement) |
76 | 102 | - `if (condition) { /* code */ }` (conditional statement) |
77 | 103 | - `return result;` (return statement) |
78 | 104 |
|
79 | | -Some constructs serve both roles. For example, `Math.Max(a, b)` is an expression when used in `int result = Math.Max(a, b);`, but becomes an expression statement when written alone as `Math.Max(a, b);`. |
| 105 | +Statements often contain expressions, and expressions can nest inside other expressions. For example, the following declaration statement assigns `f` to the result of an addition expression. That addition expression adds the results of two method call expressions: |
| 106 | + |
| 107 | +```csharp |
| 108 | +var f = Math.Max(a, b) + Math.Max(c, d); |
| 109 | +``` |
80 | 110 |
|
81 | 111 | For detailed information about statements, see [Statements](../../programming-guide/statements-expressions-operators/statements.md). For information about expression-bodied members, see [Expression-bodied members](../../programming-guide/statements-expressions-operators/expression-bodied-members.md). |
82 | 112 |
|
|
0 commit comments