1.3. C# Program Structure#
1.3.1. The .NET Templates#
The .NET SDK comes with built-in templates for creating projects and files, including console apps,
class libraries, unit test projects, etc. For learning purposes, we will mainly use the console app
template. To see the list of templates, you may issue the dotnet new list command:
PS C:\> dotnet new list
These templates matched your input:
Template Name Short Name Language Tags
---------------------------------- -------------- ---------- ------------------------
API Controller apicontroller [C#] Web/ASP.NET
ASP.NET Core Empty web [C#],F# Web/Empty
ASP.NET Core Web API webapi [C#],F# Web/Web API/API/Service
...
ASP.NET Core Web App (Razor Pages) webapp,razor [C#],F# Web/MVC/Razor Pages
Blazor Web App blazor [C#] Web/Blazor/WebAssembly
Class Library classlib [C#],F#,VB Common/Library
Console App console [C#],F#,VB Common/Console
...
1.3.2. A Console App#
We can try out the Console App template, which will give us a “Hello, World” message
when executing. In the terminal, let us
change directory (cd) into the test directory and issue command dotnet new console.
The .NET SDK will generate a project for us, which will include the following files and
directories:
The
Program.csfileThe
objfolderThe
testPrj.csprojfileAlso, a
bindirectory will be created later after the project is built.
PS C:\[username]> cd test
PS C:\[username]\test> dotnet new console
The template "Console App" was created successfully.
Processing post-creation actions...
Restoring C:\Users\[username]\test\test.csproj:
Restore succeeded.
PS C:\Users\[username]\test> ls
Directory: C:\Users\[username]\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/12/2026 12:40 PM obj
-a---- 3/12/2026 12:40 PM 40 Program.cs
-a---- 3/12/2026 12:40 PM 253 test.csproj
PS C:\Users\[username]\test>
From the terminal we can open vscode by typing code . and hit Enter (the dot . means the current directory; namely, open VS Code and use this current directory as project folder).
PS C:\Users\tcn85\test> code .
PS C:\Users\tcn85\test>
VS Code will open. We then choose the Explorer () view and click on the Program.cs file. You will see that the Program.cs looks simple as below and we are working the executable code directly.
1Console.WriteLine("Hello, World!");
The template is very succinct because of after C#9 there’s a feature called top-level statements, with which you write and execute code without the boilerplate class and Main method wrapper because he compiler automatically generates a Program class with an entry point method for the application and adds a set of implicit global using directives such as Microsoft.NET.Sdk to include the most common namespaces.
While top-level statements are friendly to new users and is the default when you create a new project using dotnet new console, there’s a limit that only one file in a project can have top-level statements. Therefore, as we learn more about C# programming, you will need to learn how to structure your code using namespaces and classes.
Important
There can be only one entry point (the Main() method) per C# project, but a project can have many .cs files.
A .csproj file defines a project, and a project can only have one entry point — either one file with top-level statements, or one static void Main() method. However, a project can contain as many .cs files as you like; all extra .cs files just define additional classes or helpers that the entry point can use. If you have two programs that each need their own Main(), they must be two separate projects (two separate .csproj files).
1.3.3. C# Program Structure#
1.3.3.1. Creating a C# Project#
To use the conventional C# program style, you use the --use-program-main option to create a console app project with the Main method. In the example below, we create a test2 folder, change into the test2 folder, then issue dotnet new console with the option --use-program-main to create the project with conventional Program.cs structure:
PS C:\Users\[username]> mkdir test2
Directory: C:\Users\[username]
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/13/2026 12:12 AM test2
PS C:\Users\[username]> cd test2
PS C:\Users\[username]\test2> dotnet new console --use-program-main
The template "Console App" was created successfully.
Processing post-creation actions...
Restoring C:\Users\[username]\test2\test2.csproj:
Restore succeeded.
After creating the project, we first `ls` (list) the folder to see what files and directories are there.
```powershell
PS C:\Users\[username]\test2> ls
Directory: C:\Users\[username]\test2
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/13/2026 12:12 AM obj
-a---- 3/13/2026 12:12 AM 140 Program.cs
-a---- 3/13/2026 12:12 AM 253 test2.csproj
This will give us the same project files as running dotnet new console without the --use-program-main option, but the Program.cs file will be different. Opening the Program.cs and you see the template code as:
namespace testPrj;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
The boilerplate code above actually means we formally wrap our C# code around in layers when our project scale go beyond a simple script:
┌─────────────────────────────────────────┐
│ namespace testPrj │
│ ┌───────────────────────────────────┐ │
│ │ class Program │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ static void Main(string[]) │ │ │
│ │ │ { │ │ │
│ │ │ // statements here │ │ │
│ │ │ } │ │ │
│ │ └─────────────────────────────┘ │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
1.3.3.2. The Program.cs#
Some important concepts that you need to learn from this template code example here so we have better ideas about the basic structure of C# programs.
using System;:Starting .NET 6,
using Systemis implicit as defined in the.csprojfile so it is not shown in the Program.cs file. We should know that,Systemis a root-level namespace that contains basic defined value and reference types. Theusingdirective allows you to use the types defined in a namespace without specifying the fully qualified namespace of that type. For example,Consoleis a class inside theSystemnamespace and we use itsWriteLinemethod to print to the console by typingConsole.WriteLine(), less theSystempart.using System; Console.WriteLine("Hello"); // instead of System.Console.WriteLine
namespace: Thenamespacekeyword is used to declare a scope to organize types (such as classes). For example, following the template’s program structure, we may define a namespace as below to contain unique code elements such as class, interface, struct, which will be implemented to create functionalities for the application.namespace SampleNamespace { class SampleClass { } interface ISampleInterface { } struct SampleStruct { } enum SampleEnum { a, b } delegate void SampleDelegate(int i); namespace Nested { class SampleClass2 { } } }
An example of namespace is the
Systemnamespace in .NET, which defines some of the fundamental types. When we runConsole.WriteLine("Hello, World");, we are actually runningSystem.Console.WriteLine("Hello World!");We do not specify “System” because it is “imported” (by the hiddenusing System) already and we can use the fundamental features (e.g.,Console,String,Math, etc) within the namespace. Software engineers use namespace the same way to organize the functionalities in applications. [1]class: A class is a blueprint for creating objects. It is a user-defined reference type that defines:fields/properties (data that describe the object), and
methods (functions that define the object’s behavior).
By convention, each class is defined in its own file, named after the class (e.g., MyClass.cs).
The
Mainmethod: The Main method is the entry point of a C# application and therefore the first method invoked when an application is executed. There is only one entry point in a C# program.method: A method (function) is an object-oriented term for function, which is a series of statements designed to perform certain task. In C#, just like Java, the Main method is the entry point of the program, meaning it is the first method invoked when a program is executed.static&void:The modifier
staticmeans the method can be called without creating a new object from the class.voidmeans the Main method does not return anything.
string[] args: Theargsare called “command line arguments” and in this example the type is string array; meaning when calling this method you send the arguments in and they are zero-indexed as an array.
1.3.3.3. Top-Level Statements#
When you create a real console project with dotnet new console (without the option --use-program-main), the generated Program.cs uses top-level statements (the default since .NET 6), which lets you write code without explicitly declaring class Program and Main. You still create a project and it still compiles into a proper executable, but the compiler automatically wraps the top-level statements into an entry point, which is equivalent to the explicit class Program / static void Main. As you might have noticed, the Program.cs
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
1.3.3.4. Script Mode#
When you enable the Live Code mode of the page, you can write and run C# inside the code cells (but not markdown cells), the .NET Interactive kernel, similar to csharprepl, runs code in script mode: you write statements directly without creating a project wrapping code in a namespace, class, or Main method. This is similar to how Python or JavaScript work in their REPL.
Script mode (notebook) |
Top-level statements (project) |
Explicit |
|
|---|---|---|---|
|
not supported |
optional |
optional |
|
can do but not needed |
can do but not needed |
required |
Compiles to |
interpreted/runs in-memory |
supported |
supported |
How to create |
.NET Interactive notebooks |
|
|
In this book, notebooks use script mode for interactive exploration, while the companion C# projects use top-level statements or the explicit Main form depending on context.
1.3.4. Solutions and Projects#
For simple project, you can create a project without creating a solution. To do that, create a directory in command line, and issue the command such as dotnet new console --use-program-main to use the .NET templates for creating new projects. A .csproj file will be created and you know that this is a project folder.
For more complicated projects, the .NET platform uses solutions and projects to organize code items in specific structure. A solution is a container or workspace for one or more projects, and each project would contain source code files. A web app solution, for example, may include a website project, a database project, and a server-side API project; and each of the project will be named differently under different project folders inside the solution directory.
┌────────────────────────────────────────────────────────────────────┐
│ MySolution.sln │
│ Solution file – groups all projects │
│ │
│ ┌────────────────┐ ref ┌────────────────┐ ref ┌────────────────┐ │
│ │ MyApp.API │ ────▶ │ MyApp.Core │◀────│ MyApp.Infra │ │
│ │ │ │ │ │ │ │
│ │ .csproj │ │ .csproj │ │ .csproj │ │
│ │ Controllers, │ │ Models, │ │ DB, │ │
│ │ endpoints │ │ interfaces │ │ repositories │ │
│ └────────────────┘ └───────▲────────┘ └────────────────┘ │
│ ref│ │
│ ┌────────┴───────┐ │
│ │ MyApp.Tests │ │
│ │ │ │
│ │ .csproj │ │
│ │ Unit & │ │
│ │ integration │ │
│ │ tests │ │
│ └────────────────┘ │
└────────────────────────────────────────────────────────────────────┘
To create a solution as a workspace, we use the command dotnet new sln in the solution directory. You then create all your project directories in the solution directory, and then create a new project in each of the project directories using the .NET templates (e.g., Console App or Web App).
MySolution/
├── MySolution.sln
├── MyApp/
│ └── MyApp.csproj
├── MyLibrary/
│ └── MyLibrary.csproj
└── MyTests/
└── MyTests.csproj
To manage your projects and solutions, you can:
Create a new solution
dotnet new sln -n MySolution
Create a project
dotnet new console -n MyApp dotnet new classlib -n MyLibrary
Add projects to the solution
dotnet sln MySolution.sln add MyApp/MyApp.csproj dotnet sln MySolution.sln add MyLibrary/MyLibrary.csproj
Common solution commands for further management of projects and solutions include:
Task |
Command |
|---|---|
List projects in solution |
|
Remove a project |
|
Add project reference |
|
Build entire solution |
|
Run a specific project |
|
Add a NuGet package |
|
If you create a project in a folder using VS Code’s “Create .NET Project” button in the Explorer view, a solution will be created with the same name as the project. To manage solutions, the Solution Explorer in VS Code can be used, with the C# Dev Kit extension installed. The Solution Explorer panel in the sidebar allows you to:
Add/remove projects
Manage NuGet packages
View project references
Run/debug projects [2].
1.3.5. Comments, Curly Braces, and Semicolon#
Comments are important as they make code more readable. C# offers single-line and multiple-line comments:
Single-line Comments: Single-line comments start with two forward slashes (//). Any text between // and the end of the line is ignored by C# (will not be executed).
Multi-line Comments: Multi-line comments start with /* and ends with */. Any text between /* and */ will be ignored by C#.
The curly braces { } in C# mark the beginning and the end of a block of code.
Semicolons work as statement terminator character in C# and are required because they prevent syntax ambiguities. Semicolons after method or accessor block, however, is not allowed.
1.3.5.1. Compound Statements (Code Blocks)#
A code block (or simply “block”), also referred to as a compound statement, is the grouping of multiple statements into a single statement. While each statement that ends with a semicolon, often it makes sense to see a block of statements as one lexical unit. In C#, a code block is delimited by a pair of curly braces to include a list of statements. For example, the following code shows an if statement, you can see the two highlighted code blocks being compound statements because the statements inside the curly braces. More specifically, line 4-9 is a compound statement of the if statement.
Footnotes