.NET CLI — fra enkelt C#-fil til solution

Kommandolinje (CLI) til at oprette, køre, bygge og publicere .NET-programmer

CLI betyder Command Line Interface — kommandolinjen (Terminal, PowerShell, cmd). Kommandoerne her skrives som tekst, ikke via knapper i en GUI. Er du ny: start roligt, kopiér én kommando ad gangen, og læs hvad den gør, før du kører den.
Windows og macOS
Når en kommando er ens på begge systemer, vises den kun én gang. Når stier eller værktøjer varierer mellem Windows og macOS, er de opdelt ved siden af hinanden. På små skærme placeres de automatisk under hinanden.

1. Enkelt-fil: hurtig reference


    dotnet --version                         # show installed .NET SDK version
    dotnet file.cs                            # run a C# file
    dotnet run file.cs                        # run a C# file
    dotnet build file.cs                      # build a C# file
    dotnet restore file.cs                    # restore NuGet packages
    dotnet publish file.cs                    # publish the application
    dotnet clean file.cs                      # clean build output
    
    #:package PackageName@1.2.3               # add a NuGet package
    #:project ../Library/Library.csproj       # reference a project
    #:property TargetFramework=net10.0        # set a .NET property

Den vigtigste kommando at starte med er:


    dotnet hello.cs

.NET 10 kan automatisk kompilere og køre filen uden en .csproj-fil.

2. Situation: Jeg vil bare lave en C#-fil og prøve noget simpelt

Forestil dig en elev, der bare vil undersøge en idé. Hun starter med at åbne sin terminal og gå til sin arbejdsmappe (hvor username udskiftes med eget brugernavn, samme med Dropbox skydrev):

Windows (cmd.exe)
cmd.exe
cd C:\Users\username\Dropbox\csh\players
macOS (Terminal)
Terminal
cd /Users/username/Dropbox/csh/players

Hun opretter derefter en tom C#-fil:

Windows (cmd.exe)
type nul > page068-consolas.cs
macOS (Terminal)
touch page068-consolas.cs

Filen kan derefter åbnes og redigeres i en teksteditor, et simpelt eksempel er at give filen indholdet:


    Console.WriteLine("Hello, World!");

Hvis hun vil se filens indhold direkte fra kommandolinjen:

Windows (cmd.exe)
type page068-consolas.cs
macOS (Terminal)
cat page068-consolas.cs

Når filen er gemt til harddisk, kan den køres direkte med:


    dotnet run page068-consolas.cs
    Hello, World! 

.NET bygger og kører programmet:


    hello.cs
       ↓
    dotnet hello.cs
       ↓
    programmet kører

Det er især velegnet til små programmer, undervisning, eksperimenter og små hjælpeprogrammer.

3. Enkelt-fil med flere linjer og almindelig C#

File-based apps er stadig almindelige C#-programmer. Man kan eksempelvis skrive (antager filen program.cs):


    string name = "Linus";
    Console.WriteLine($"Hello {name}!");
    for (int i = 1; i <= 5; i++)
    {
        Console.WriteLine(i);
    }

Og køre:


    dotnet program.cs

Man behøver altså ikke lære en ny "script-version" af C#. Det er ægte C#, som .NET SDK'en håndterer direkte fra filen.

4. Enkelt-fil og NuGet

På et tidspunkt vil eleven måske bruge noget, som ikke findes i det almindelige .NET-bibliotek.
I en file-based app kan en NuGet-pakke angives direkte i C#-filen med et #:package-direktiv:


    #:package Spectre.Console@0.54.0
    using Spectre.Console;
    
    AnsiConsole.MarkupLine("[green]Hello![/]");

NuGet-dependency'en er altså skrevet direkte sammen med programmet. .NET 10 understøtter #:package-direktivet til file-based apps. .NET sørger for at restore den nødvendige pakke, hvis den ikke allerede er tilgængelig. Restore sker normalt implicit ved build eller run.

5. Hvornår bliver én fil for lille?

Forestil dig nu, at programmet vokser og får flere klasser:


    Program.cs
    Player.cs
    Enemy.cs
    Game.cs

Der kommer måske også NuGet-pakker, konfiguration, tests og andre filer. Nu er det ikke længere bare et lille eksperiment. Og måske ønsker programmøren at debugge koden. Så er det naturligt at gå videre fra enkelt-fil til et .NET-projekt.

6. Projekt: hurtig reference


    dotnet new console -o MyApp  # opretter et nyt projekt 
    #   i en ny undermappe der hvor kommandoen skrives
    dotnet new console -o MyApp --use-program-main
    #   inkluderer namespace, klassen Program og metoden Main(). 
    dotnet new list              # lister skabeloner (kan hente flere)
    dotnet new list console      # Beskriver console skabelonen! 
    dotnet new console --help    # viser hjælp til "dotnet new console"
    
    dotnet run                   # run project
    dotnet build                 # build project
    dotnet clean                 # clean build output
    dotnet restore               # restore NuGet packages
    dotnet test                  # run tests
    
    dotnet add package PackageName     # add NuGet package
    dotnet remove package PackageName  # remove NuGet package
    dotnet list package                # list NuGet packages
    
    # add project reference: 
    dotnet add reference ../Library/Library.csproj
    # remove project reference: 
    dotnet remove reference ../Library/Library.csproj
    
    dotnet publish                     # publish application

7. Situation: Jeg vil have et lille projekt

Eleven ønsker at kunne debugge og går derfor fra enkelt-fil til projekt.

Windows (cmd.exe)
cd C:\Users\username\Dropbox\csh\
cd playersProj
                
macOS (Terminal)
cd /Users/username/Dropbox/csh
cd playersProj
                

Forudsætter, at mappen playersProj allerede findes. Hun opretter nu projektet og går ind i folderen.


    dotnet new console -o page068consolas  # eller med Program.Main(): 
    dotnet new console -o page068consolas --use-program-main 
    cd page068consolas

.NET opretter blandt andet:


    page068consolas/
        page068consolas.csproj
        Program.cs

8. Tilføj NuGet-pakke til projekt

Projekter bruger ofte NuGet pakker, så man ikke skal opfinde det hele selv. Tilføj en pakke, f.eks. Spectre.Console med:


    dotnet add package Spectre.Console

Nu bliver package dependency'en en del af projektets konfiguration. Man kan se projektets packages med:


    dotnet list package

I den lille file-based app kan dependency'en stå direkte i .cs-filen (#:package Spectre.Console@0.54.0), mens den i et traditionelt projekt ligger i projektets .csproj.

9. Projektet vokser

Det er god programmeringsskik at placere klasser i separate cs-filer, og vi forestiller os nu at programmet får flere filer, f.eks.:


    MyApp/
        MyApp.csproj
        Program.cs
        Player.cs
        Enemy.cs
        Game.cs

.NET SDK'en ved, automatisk, at disse filer hører til projektet, fordi de ligger i projektfolderen eller dens underfoldere. Man skal derfor ikke gøre noget ekstra for at få filerne med. Man kan direkte bygge projektet med dotnet build og køre det med dotnet run (begge køres fra projektfolderen)

10. Fra file-based app til projekt (Hmmm)

.NET 10 indeholder også en interessant bro mellem de to modeller. En file-based app kan konverteres til et traditionelt projekt med:


    dotnet project convert program.cs

.NET kan dermed oprette en .csproj med tilsvarende indstillinger og package references, men den laver ikke .cs filen om til Program.cs.

11. Solution: hurtig reference

Visual Studio 2026 opretter altid en solution, også selvom vi kun beder om et projekt (med mindre vi er i en solution). Årsagen er at det kan håndtere større projekter hvor man deler opgaverne op i flere projekter (C#/.NET projekter).


    dotnet new sln -o MySolution          # opretter ny solution (.slnx)
    #   i en ny undermappe MySolution, hvor kommandoen skrives.  
    dotnet new sln --format sln           # create traditional .sln
    dotnet new sln --format slnx          # create .slnx explicitly
    
    dotnet sln list                       # list projects in solution
    dotnet sln add MyApp/MyApp.csproj     # add project
    dotnet sln remove MyApp/MyApp.csproj  # remove project
    
    # add project reference: 
    dotnet add MyApp/MyApp.csproj reference MyApp.Core/MyApp.Core.csproj
                                               
    dotnet build MySolution.slnx          # build solution
    dotnet test MySolution.slnx           # test solution

I .NET 10 er .slnx standardformatet, når man bruger dotnet new sln. Det traditionelle .sln-format findes stadig og kan vælges eksplicit med --format sln.

12. Situation: Vi vil være VS2026 kompatible

Forestil dig nu, at MyApp er blevet et større program. Udviklerne vil gerne holde forskellige dele adskilt og bruge Git til at dele projektet. Eller forestil dig at du gerne vil kunne åbne projektet i VS2026 som kræver (eller automatisk konverterer til) solution. En professionel struktur er at anvende opdelinger der ligner følgende:


    MySolution/
    │
    ├── MyApp/
    │   └── MyApp.csproj
    │
    ├── MyApp.Core/
    │   └── MyApp.Core.csproj
    │
    └── MyApp.Tests/
        └── MyApp.Tests.csproj

13. Opret solution og projekter

Åben cmd eller terminal og skift til dit C# område:

Windows (cmd.exe)
cd C:\Users\username\source\repos\csh\
macOS (Terminal)
cd /Users/username/source/repos/csh/

Opret dernæst din solution:


    dotnet new sln -o MySolution
    cd MySolution

I .NET 10 bliver det som udgangspunkt en MySolution.slnx. Ønskes den ældre type, bruges dotnet new sln -o MySolution --format sln.

14. Opret og tilføj projekterne

Her antages at du ikke har projektet eller projekterne på forhånd og skal oprette dem fra bunden:

cd MySolution
dotnet new console -o MyApp --use-program-main
dotnet new classlib -o MyApp.Core
dotnet new xunit -o MyApp.Tests

Derefter tilføjes projekterne til solution'en:


    dotnet sln add MyApp/MyApp.csproj
    dotnet sln add MyApp.Core/MyApp.Core.csproj
    dotnet sln add MyApp.Tests/MyApp.Tests.csproj

15. Tilføj eksisterende projekt

Her antages at du allerede har et projekt som du ønsker, fysisk, at flytte ind i undermappe til Solution.

Skift først folder til folder over dit projekt, f.eks. antager vi her at de ligger i source/repos:

Åben cmd eller terminal og skift til dit C# område:

Windows (cmd.exe)
cd C:\Users\username\source\repos\csh\
macOS (Terminal)
cd /Users/username/source/repos/csh/

Flyt derefter projektfolder (og indhold) til solution folder):

Windows (cmd.exe)
move PathToProject PathToSol
move MyProj MySolution # eksempel
macOS (Terminal)
mv PathToProject PathToSol
mv MyProj MySolution # eksempel

16. Projekt-reference

Projekter skal nogengange bruge metoder eller klasser fra andre projekter. Det klares med projekt-referencer, eller med NuGet pakker. Her vises projekt-referencer.

Eksempel: MyApp skal bruge kode fra MyApp.Core. Da MyApp.Core er vores egen kode, laver vi en project reference:

dotnet add MyApp/MyApp.csproj reference MyApp.Core/MyApp.Core.csproj

Tests skal også kunne bruge den centrale kode:

dotnet add MyApp.Tests/MyApp.Tests.csproj reference MyApp.Core/MyApp.Core.csproj

Vi har dermed to forskellige former for afhængighed:

Dependency Eksempel Betydning
NuGet package Serilog Ekstern kode fra et package repository
Project reference MyApp → MyApp.Core Vores eget andet projekt

17. Den samlede model


    ENKELT-FIL
    
    program.cs
        │
        ├── #:package SomePackage
        │
        ↓
        
    PROJEKT
    
    MyApp/
        MyApp.csproj
        Program.cs
        Player.cs
        Enemy.cs
        │
        ├── NuGet packages
        │
        ↓

    SOLUTION
    
    MySolution.slnx
    │
    ├── MyApp
    │   └── MyApp.csproj
    │
    ├── MyApp.Core
    │   └── MyApp.Core.csproj
    │
    └── MyApp.Tests
        └── MyApp.Tests.csproj
            │
            ├── NuGet packages
            └── Project references

18. Hvad er forskellen på de tre niveauer?

Enkelt-fil Projekt Solution
Én C#-fil Flere filer Flere projekter
Ingen .csproj .csproj .slnx eller .sln
God til eksperimenter God til et normalt program God til større løsninger
Kan bruge NuGet Kan bruge NuGet Projekterne kan bruge NuGet
Kan være meget lille Samler programmets filer Samler projekterne