With your development environment now set up, it's time to create your first real project: BiblioTechConsole, the first building block of the BiblioTech system we'll build throughout the course. In this lesson you'll create the project step by step, write and run a "Hello World", and we'll analyze line by line every part of the code, covering both the classic form and the modern (top-level statements) form of writing it. Understanding this minimal structure well is essential, because it will be the foundation all the code you write in the coming modules will rest on.

Contents

  1. Creating the BiblioTechConsole project step by step
  2. Writing and running the first Hello World
  3. Line-by-line explanation of the classic version
  4. The modern variant: top-level statements
  5. Building and running with dotnet run

Creating the BiblioTechConsole project step by step

Open a terminal in the folder where you want to keep your course projects and run:

dotnet new console -o BiblioTechConsole
cd BiblioTechConsole

As we saw in the previous lesson, this command creates a BiblioTechConsole folder with the basic structure of a console project:

BiblioTechConsole/
├── BiblioTechConsole.csproj
└── Program.cs

Open the BiblioTechConsole folder with your editor (VS Code, Visual Studio, or Rider) and locate the Program.cs file. By default, this file contains a small sample program generated automatically by the template:

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

This is the modern version (with top-level statements) that dotnet new console generates in current SDK versions. Let's modify it to talk about BiblioTech instead:

Console.WriteLine("Welcome to BiblioTechConsole!");

You can remove the automatically generated comment (the line starting with //); it isn't needed for the program to work, it's just informational text added by the template.

Writing and running the first Hello World

Save the Program.cs file with the content above and, from the terminal, inside the project folder, run:

dotnet run

You should see in the terminal:

Welcome to BiblioTechConsole!

Congratulations! You've just written and run your first C# program. Simple as it may look, this small program already puts several fundamental language concepts into play, which we'll now dissect.

Line-by-line explanation of the classic version

Before top-level statements were introduced (starting with C# 9, in 2020), every C# console program had to be written with a more explicit structure. It's very important to know this classic form, because:

  • It's what you'll find in a huge amount of existing code, documentation, and older tutorials.
  • It's actually what the compiler generates "underneath" even when we use the modern, simplified form.

Here's how our same program would look in its classic, complete form:

using System;

namespace BiblioTechConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Welcome to BiblioTechConsole!");
        }
    }
}

Let's explain each line, from top to bottom:

Line What it is Explanation
using System; using directive Indicates that this file will use types from the System namespace, where, among other things, the Console class lives. Without this line, we would have to write System.Console.WriteLine(...) every time.
namespace BiblioTechConsole Namespace declaration A namespace groups related code under a common name, avoiding conflicts with classes of the same name defined in other libraries. It usually matches the project's name.
class Program Class declaration In C#, all executable code lives inside a class. By convention, the class containing the program's entry point is called Program. We won't go deep into what a class is yet: that comes in Module 3; for now it's enough to know it's the mandatory "container" for the code.
static void Main(string[] args) The Main method This is the program's entry point: the first and only instruction the CLR runs on startup. static means it can be called without needing an object of type Program (an OOP topic, Module 3); void indicates the method returns no value; string[] args is an array of command-line arguments, which we'll cover in the next lesson.
Console.WriteLine("..."); Statement The only "real" line of code in the program: it writes the given text to the console and moves to a new line.
The braces { } Block delimiters Each { opens a block of code and its matching } closes it. The namespace, the class, and the Main method are each a block delimited by braces.

It's important to notice the nesting: the namespace contains the class, the class contains the Main method, and the Main method contains the Console.WriteLine statement. This hierarchy of braces is the general structure of (almost) any .cs file you'll write, and we'll revisit it in more detail in the next lesson, "Basic Syntax and Structure".

The modern variant: top-level statements

Since C# 9, the language lets you omit all the "scaffolding" code (namespace, class, Main method) when the program is simple, leaving only the statements that actually matter. This is called top-level statements. It's exactly what dotnet new console generated when it created your project:

Console.WriteLine("Welcome to BiblioTechConsole!");

So what happened to everything else? The C# compiler still generates the same structure underneath (namespace, class Program, static void Main) automatically; you simply don't have to write it yourself. It's exactly the same program, just with less boilerplate to write and read.

Aspect Classic form Top-level statements
Code you have to write Namespace + class + Main method + statements Only the statements
Compiled result Identical Identical
When to use it Large programs with several classes, or when more than one explicit entry point is needed Simple console programs, scripts, learning projects
Available since Always C# 9 (2020) onward

By default, in this course we'll use top-level statements for simple console examples (especially in this first module), because they let us focus on the concept being learned without getting distracted by boilerplate code. When we get to Object-Oriented Programming (Module 3), where we'll define our own classes (Book, Member, Loan), it will again become common to see structures closer to the classic form, combined with Main as the entry point.

Can I use args (command-line arguments) with top-level statements?

Yes. Even though string[] args isn't declared explicitly, the system makes an implicit variable called args available to you if you need it:

if (args.Length > 0)
{
    Console.WriteLine($"Hello, {args[0]}!");
}
else
{
    Console.WriteLine("Welcome to BiblioTechConsole!");
}

Don't worry if you don't yet understand if or the $"..." interpolation: we'll cover them in detail in Modules 2 and 6 respectively (control flow and strings). This is just so you know that the args variable is still available even though the Main method isn't visible explicitly.

Building and running with dotnet run

We already used dotnet run to run our program, but it's worth understanding exactly what happens "under the hood" when we launch it:

  1. Dependency restoration: dotnet checks whether the project needs to download any external packages (none, in our case, so far) and prepares them if needed.
  2. Compilation: the C# compiler translates the source code (Program.cs) into intermediate language (IL), generating an executable inside the bin/ folder.
  3. Execution: the CLR loads that executable and runs it, compiling the IL to machine code on the fly (JIT compilation, mentioned in the first lesson).

If you just want to build without running (for example, to check there are no errors without seeing the output on screen), you can use:

dotnet build

And if you want to run the already-built executable directly (without going through the whole build process again), you can find it inside bin/Debug/net8.0/ and run it straight from there. In practice, while learning, dotnet run is the most convenient way, and it's what we'll use throughout the course.

Editing and re-running

A common workflow while learning is: edit Program.cs, save, and run dotnet run again. For example, try adding a second line to your program:

Console.WriteLine("Welcome to BiblioTechConsole!");
Console.WriteLine("Library management system");

Running dotnet run again, you'll see both lines in the terminal, one below the other, because WriteLine always adds a line break at the end of whatever it writes.

Common Mistakes and Tips

  • Forgetting the semicolon ; at the end of a statement: this is one of the most frequent mistakes when starting out. The compiler will show an error message pointing to the exact line.
  • Saving the file but running from the wrong folder: dotnet run must be run from the project folder (where the .csproj file is), not from a folder above or below it.
  • Thinking you always have to write out the full classic form: that's not the case; for simple programs, top-level statements are perfectly valid, and in fact are the form the official dotnet new console template generates.
  • Confusing Console.Write with Console.WriteLine: Write writes the text without moving to a new line; WriteLine does move to a new line at the end. If two consecutive messages appear "stuck together" on the same line, you probably used Write instead of WriteLine.
  • Tip: when the compiler shows an error, read it calmly: it usually points to the file, the line, and a fairly precise description of what's wrong (for example, "a semicolon is missing" or "that name could not be found").

Exercises

  1. Create the BiblioTechConsole project by following the steps in this lesson (if you haven't already) and modify Program.cs so that, using top-level statements, it writes two lines: one with the system's name ("BiblioTechConsole") and another with a welcome message of your choice. Run the program with dotnet run and check the result.

  2. Rewrite the program from the previous exercise using the full classic form (using, namespace, class Program, static void Main), keeping the same behavior (the same two output lines). Run it and check that the on-screen result is identical to exercise 1.

  3. Using the implicit args variable in the top-level statements version, write a program that shows "Welcome to BiblioTechConsole!" if no argument is passed, or a personalized greeting if one is passed. (Hint: in most editors you can configure command-line arguments in the debug/run options; if you don't know how to do that yet, don't worry, just focus on getting the code to compile correctly).

Solutions

  1. Contents of Program.cs:

    Console.WriteLine("BiblioTechConsole");
    Console.WriteLine("Welcome to the library management system!");
    

    Running dotnet run should show both lines in the terminal, one below the other.

  2. Equivalent classic version:

    using System;
    
    namespace BiblioTechConsole
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("BiblioTechConsole");
                Console.WriteLine("Welcome to the library management system!");
            }
        }
    }
    

    The on-screen result is exactly the same as in exercise 1, because both forms compile, essentially, to the same program.

  3. Sample solution:

    if (args.Length > 0)
    {
        Console.WriteLine($"Hello, {args[0]}! Welcome to BiblioTechConsole.");
    }
    else
    {
        Console.WriteLine("Welcome to BiblioTechConsole!");
    }
    

    If the program runs with no arguments, the generic message is shown; if an argument is passed (for example, a name), the personalized greeting is shown. There's no need to fully understand if or $"..." interpolation yet: we'll cover them in detail later in the course.

Conclusion

In this lesson you created your first real project of the course, BiblioTechConsole, and learned to tell apart the classic structure of a C# program (namespace, class, Main method) from the modern form with top-level statements, understanding that both produce exactly the same result. You also practiced the full cycle of editing and running with dotnet run.

Now that you know how to create and run programs, it's time to dig into the syntax rules that govern any C# file: case sensitivity, blocks delimited by braces, comment types, and naming conventions. That's exactly what we'll cover in the next lesson, Basic Syntax and Structure.

© Copyright 2026. All rights reserved