Gå til indholdet

Løsning og projekt

En C# løsning (solution på engelsk – løsning på dansk er en lidt skidt oversættelse) består typisk af et eller flere projekter, og et enkelt projekt kan være en konsol-applikation (ligesom du oprettede i forrige afsnit), en web-applikation, en Windows-applikation, mobil-applikation og meget andet.

Information til undervisere

Vis kursisten indholdet i en .slnx- eller .sln-fil og en .csproj-fil. Skab eventuelt et simpelt eksempel med en løsning bestående af en konsol app og et klassebibliotek.

En løsning er repræsenteret af en .slnx- eller .sln-fil, og du kan finde en visuel repræsentation i Solution Explorer-vinduet. .slnx er det nyere, XML-baserede format, som er lettere at læse og redigere end det ældre .sln-format. Fra og med .NET 10 opretter dotnet new sln som standard en .slnx-fil, mens ældre .NET SDK-versioner typisk opretter en .sln-fil. Begge formater samler projekter i en løsning. Der kan kun være én løsning ad gangen i VS/VSC, men du må gerne have flere udviklingsmiljøer åbne på samme tid.

Tip

Hvis du arbejder med VSC, er der ikke nødvendigvis en løsningsfil. Du kan oprette en med kommandoen dotnet new sln. Vil du udtrykkeligt vælge formatet, kan du bruge dotnet new sln --format slnx eller dotnet new sln --format sln.

Hvert projekt kan være opdelt i flere filer, som kompileren vil sørge for at kompilere sammen. Et projekt er repræsenteret af en .csproj-fil, og består typisk af en eller flere .cs-filer med kode samt eventuelle konfigurationsfiler. Der kan være mange projekter under hver løsning.

Et projekt kan have en filstruktur som følger:

c:\temp\MinTest
    MinTest.slnx
    \MinTest
        MinTest.csproj
        Program.cs

Hvis du åbner .slnx-filen (eller en ældre .sln-fil) og .csproj-filen i Notepad, vil du kunne se, at det er filer, som VS bruger til at holde styr på løsningen og de tilhørende projekter. Du vil sjældent tosse rundt i disse filer, men nu ved du, hvad de består af.

Du må gerne have mange cs-filer (kodefiler) i et projekt, og du kan organisere disse, som du ønsker i mapper. Typisk vil du have en .cs-fil til hver typedefinition, og dermed ende med mange filer, men du kan også vælge at have flere typer i samme fil – kompilereren er ligeglad.

Eksempel

For at se en konkret løsning med projekter kan du gøre følgende

  • åbn en terminal og naviger til en temp-mappe c:\temp eksempelvis
  • opret en ny mappe MinApp og naviger til den
  • opret en konsol app med dotnet new console -n MinApp.Console
  • opret et klasse bibliotek med dotnet new classlib -n MinApp.ClassLibrary
  • opret en løsningsfil med dotnet new sln -n MinApp (filen bliver .slnx i .NET 10 og nyere)
  • tilføj MinApp.Console til løsningen med dotnet sln add .\MinApp.Console\MinApp.Console.csproj
  • tilføj MinApp.ClassLibrary til løsningen med dotnet sln add .\MinApp.ClassLibrary\MinApp.ClassLibrary.csproj
  • prøv en dir for at se fil strukturen
  • åbn .slnx- eller .sln-filen for at se indholdet
  • gå til MinApp.Console med cd .\MinApp.Console\
  • skab en reference fra MinApp.Console til MinApp.ClassLibrary med dotnet add reference ..\MinApp.ClassLibrary\MinApp.ClassLibrary.csproj
  • ret class1.cs i .\MinApp.ClassLibrary til
namespace MinApp.ClassLibrary;
public class Class1
{
    public static string Test()
    {
        return "Test";
    }
}
  • ret program.cs i .\MinApp.Console til
Console.WriteLine("Hello, World!");
Console.WriteLine(MinApp.ClassLibrary.Class1.Test());
  • naviger til ./MinApp.Console og kør applikation med dotnet run
  • det skulle gerne resultere i
Hello, World!
Test
  • som beviser at de to projekter er bundet sammen

Det er et kort eksempel på en løsning med to projekter. Det kan naturligvis også gøres i VS eller Rider, men mange gange er det faktisk nemmere og hurtigere at gøre fra en terminal.

Dine egne prompts til Github Copilot

Hvis du har adgang til Github Copilot (kræver et abonnement), kan du eventuelt hjælpe Copilot på vej ved at tilføje en fil med en prompt i roden af dit løsning.

Filen skal hedde copilot-instructions.md, og ligge i mappen .github. Husk - den skal ligge på samme niveau som din .slnx- eller .sln-fil (eller .csproj, hvis du ikke har nogen løsningsfil).

Du kan eksempelvis tilføje følgende indhold:

# Copilot Instructions for C# Course

These are the rules for code generation in C#:

## General Rules
- Code must always use **English** names for variables, methods, classes, etc.  
- All comments must be written in **Danish**, using `// ...`.  
- Every piece of code must be **thoroughly commented**, so that even readers with very little knowledge of C# can understand it.  
- **All other communication (outside of code)** must be written in **Danish**.  

## Structure
- Use **top-level statements** where possible.  
- All **methods** should be placed at the top scope.  
- All **types (classes, structs, etc.)** should be placed at the **bottom of the file**.  

## Best Practices
- Always follow **known best practices** for C# (naming conventions, formatting, proper use of access modifiers, etc.).  
- Do **not** use lambda expressions, delegates, or advanced language features.  
- Keep the code **simple and clear**, since it is intended for beginners.  
- Each example must be **self-contained** and runnable.  

## Example

```csharp


// Dette program demonstrerer hvordan man kan beregne gennemsnittet af tal i en liste.
// Koden er skrevet så selv begyndere kan følge med.

// ------------------------------------------------------------
// Metoder placeres altid øverst i filen (inden typer)
// ------------------------------------------------------------

// Denne metode beregner gennemsnittet af en liste af heltal
static double CalculateAverage(List<int> values)
{
    // Først tjekker vi om listen er tom
    if (values.Count == 0)
    {
        // Hvis listen er tom, returnerer vi 0
        return 0;
    }

    // Her summerer vi alle tal i listen
    int sum = 0;
    foreach (int v in values)
    {
        sum += v; // Vi lægger hvert tal til summen
    }

    // Til sidst deler vi summen med antallet af elementer for at få gennemsnittet
    return (double)sum / values.Count;
}


// Her opretter vi en liste af heltal
List<int> numbers = new List<int> { 5, 10, 15, 20, 25 };

// Vi kalder en metode for at beregne gennemsnittet
double average = CalculateAverage(numbers);

// Vi skriver resultatet ud på skærmen
Console.WriteLine("Average is: " + average);



// ------------------------------------------------------------
// Typer placeres nederst i filen
// ------------------------------------------------------------

// Denne klasse er blot et eksempel og kan bruges til at udvide programmet senere
class ExampleHelper
{
    public string Name { get; set; }
}

Dette er blot et eksempel. Du kan tilpasse instruktionerne, så de passer til dine behov.

Spørgsmål til AI

For at få mest muligt ud af AI-værktøjer som ChatGPT, er det vigtigt at stille klare og præcise spørgsmål (og skabe det rigtige kontekst - se her). Her er nogle spørgsmål til denne side:

Grundlæggende spørgsmål

  • Hvad er forskellen på en solution (.slnx eller .sln) og et projekt (.csproj) i .NET?
  • Hvad er forskellen på de to løsningsformater .slnx og .sln?
  • Hvorfor giver det mening at samle flere projekter i én løsning?
  • Kan du forklare, hvordan Solution Explorer afspejler indholdet af .sln og .csproj?
  • Hvad indeholder en typisk .csproj-fil, og hvad bruger værktøjerne den til?
  • Hvornår giver det mening at have flere .cs-filer vs. flere typer i samme fil?
  • Hvordan opretter jeg en løsning fra terminalen med dotnet new sln, og hvordan vælger jeg mellem .slnx og .sln?
  • Hvordan tilføjer jeg et eksisterende projekt til en løsning med dotnet sln add?
  • Hvordan opretter jeg en konsolapp og et klassebibliotek fra terminalen?
  • Hvordan opretter jeg en projektreference mellem to projekter (dotnet add reference) – og hvorfor?

Ekstra spørgsmål (til fordybelse)

  • Hvad sker der, hvis løsningsfilen mangler, men projekterne stadig findes – kan jeg bygge alligevel?
  • Hvordan påvirker projektreferencer build-rækkefølge og afhængigheder?
  • Hvilke alternativer findes til projektreferencer (fx pakke-referencer/NuGet), og hvornår bruger man hvad?
  • Kan du vise et mini-eksempel på et klassebibliotek med en metode, der kaldes fra en konsolapp (og forklare namespaces)?
  • Hvordan renamer man et projekt, så både mappe, .csproj-fil og namespaces hænger sammen?
  • Hvad er forskellen på dotnet run i roden af løsningen vs. inde i et bestemt projekt?
  • Hvordan opretter man en test-projektmappe og kobler den på løsningen (fx dotnet new xunit + dotnet sln add)?
  • Kan du vise, hvordan man læser og forstår de vigtigste elementer i en simpel .csproj (TargetFramework, ItemGroup, ProjectReference)?