Episode 3 is your first hands-on practice: creating a project with dotnet new, understanding the Program.cs and csproj structure, then running, building, and publishing a console application. You will feel the .NET workflow from start to a production artifact.

In episode 2 you understood the .NET architecture. Now it's time for practice: creating your first .NET application. Episode 3 guides you from zero — creating a project with dotnet new, dissecting the generated folder structure, then running, building, and publishing a console application.
The workflow you learn here is the foundation for all the following episodes. Whether it's a web API, a worker service, or a desktop app — everything is born from the same templates and uses the same CLI commands. Master this flow and the rest become small variations.
The .NET SDK already ships many built-in templates. See the list to confirm the console template is available:
dotnet new listdotnet new list shows all installed templates, for example console, classlib, webapi, mvc, worker, and maui. The output shows the Short Name, Language, and Tags columns — use the short name when creating a project.
Create your first project:
dotnet new console -n HelloDotnet -o src/HelloDotnetdotnet new console -n HelloDotnet -o src/HelloDotnet creates a project named HelloDotnet in the src/HelloDotnet folder. The -n option sets the project name (and namespace), while -o sets the output location. The main code file generated is Program.cs.
Open Program.cs — its content is roughly as follows:
Console.WriteLine("Hello, World!");.NET 6 and later use top-level statements, so you don't need to write a class and Main method explicitly — the compiler wraps them for you. The line Console.WriteLine("Hello, World!") prints text to standard output, and that line is your application's entry point.
The important companion file is HelloDotnet.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project><TargetFramework>net8.0</TargetFramework> sets the target runtime version. ImplicitUsings automatically adds common usings, and Nullable enables nullable reference types analysis. The obj and bin folders contain temporary build artifacts — neither needs to be committed to Git.
Run the application from the project root:
dotnet rundotnet run performs restore, build, and then runs the application. The Hello, World! output will appear. This command is the fastest way to test small changes. For development that watches file changes automatically, use hot reload:
dotnet watch rundotnet watch run monitors source changes and restarts the application automatically — a workflow that's very helpful when developing a web API in episode 11.
Before committing, get into the habit of building explicitly to make sure your code is error-free:
dotnet build --configuration Releasedotnet build --configuration Release compiles the project in Release mode and produces the assembly in bin/Release/net8.0/. The resulting artifacts still require the .NET runtime to be installed on the target machine.
For distribution, use publish. Self-contained mode carries its own .NET runtime, so the target doesn't need .NET installed:
dotnet publish -c Release -r linux-x64 --self-contained truedotnet publish produces the bin/Release/net8.0/linux-x64/publish/ folder containing the complete application plus the runtime. That folder is what will become the Docker image in episode 19.
Tip
Framework-dependent (without -r) produces small artifacts but needs the runtime on the target. Self-contained is larger yet self-sufficient. Choose based on your deployment environment.
A summary of the commands you'll use every day:
dotnet new to create a project from a template.dotnet run to run while developing.dotnet watch run for hot reload.dotnet build to verify compilation.dotnet publish to produce a production artifact.dotnet test to run unit tests (episode 18).Key takeaways:
dotnet new console -n Name -o Path creates a new project.dotnet run runs the application; dotnet watch run adds hot reload.dotnet build verifies compilation; dotnet publish produces artifacts.In the next episode 4 we will discuss basic language and data types — primitive types, value and reference types, nullable, strings, structs and enums, control flow, and functions and lambda expressions in C#. This is the core of writing .NET application logic.