# C# snabbreferens

Detta är en hemsida med förenklade förklaringar och exempel för C# och Visual Studio Code. Tanken är att den ska kunna användas som referensverk för gymnasieelever som läser kurserna **Programmering 1** och **Programmering 2**.

**Se även:**

* [Progdocs](https://www.progdocs.se/) – en portal med olika dokumentations-sajter som denna.
* [Unity](https://unity.progdocs.se/) – en sida med förenklade förklaringar och exempel för Unity och C#

## Vad behöver jag först?

* Installera [.NET SDK](/mjukvara/dotnet-sdk) – version 9 eller senare: <https://dotnet.microsoft.com/en-us/download>
* Installera [Visual Studio Code](/mjukvara/visual-studio-code)
  * Och lämpliga [extensions](/mjukvara/visual-studio-code/extensions).
  * Ställ in så program [körs i ett eget fönster](/mjukvara/visual-studio-code/instaellningar#kor-eller-debugga-i-separat-fonster)
* Installera [Git-scm](/mjukvara/git-and-github) och [ställ in namn och email](/mjukvara/git-and-github#forsta-gangen-efter-ny-git-installation).
* Kolla [lathunden ](/lathund-skapa-projekt)för hur man skapar nya projekt.

Det enklaste sättet att installera .NET SDK, Visual Studio Code och Git-scm är via **winget**. Öppna ett terminalfönster/kommandotolken och kör:

```powershell
winget install Microsoft.VisualStudioCode
winget install git.git
winget install Microsoft.DotNet.SDK.10
```

Winget bör finnas och fungera i Windows 10 och 11; använder du en äldre version av windows kanske du får installera manuellt istället. Det kan också vara bra att köra **Windows Update** först, och installera alla tillgängliga uppdateringar (inklusive de man bara får om man klickar "Sök online…"

{% hint style="info" %}
**TIPS:** winget kan användas för att installera [allt möjligt](https://winget.run/), och kan också hålla programmen uppdaterade.

Om du skriver <mark style="color:orange;">`winget upgrade`</mark> så får du en lista med program som kan uppdateras, och du kan då antingen skriva <mark style="color:orange;">`winget upgrade <namnet på programmet>`</mark> för att uppdatera ett specifikt program eller <mark style="color:orange;">`winget upgrade --all`</mark> för att uppdatera alla.
{% endhint %}

## Hittat ett fel?

Hela den här sidan finns [speglad på GitHub](https://github.com/krank/csharp-ref) – där kan du skapa en buggrapport (issue) och beskriva problemet.

Eller så kan du forka repositoriet, göra ändringen och sedan göra en pull request!

## Progression

Den här sidan är byggd för kurserna Programmering 1 och 2, och detta är den tänkta uppdelningen.

Vissa saker som t.ex. [Raylib ](/annat/raylib)ligger utanför tabellen – det är inte ett obligatoriskt moment i någon kurs men är heller inte riktigt "överkurs".

| Programmering 1                                                       | Programmering 2                                                                              | Överkurs                                                            |
| --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| [Datatyper](/grundlaggande/datatyper)                                 | [Klasser och instanser](/klasser-och-objektorientering/klasser-och-instanser)                | [Delegates, events och lambdas](/grundlaggande/delegates)           |
| [Typkonvertering](/grundlaggande/typkonvertering)                     | [Public, private och protected](/klasser-och-objektorientering/public-private-och-protected) | [Reference vs value types](/grundlaggande/reference-vs-value-types) |
| [Operatorer](/grundlaggande/operatorer)                               | [Klassdiagram](/klasser-och-objektorientering/klassdiagram)                                  | [Abstract](/klasser-och-objektorientering/abstract)                 |
| [Konsolen](/grundlaggande/konsollen-console)                          | [Klassmetoder](/klasser-och-objektorientering/klassmetoder)                                  | [Interface](/klasser-och-objektorientering/interface)               |
| [If-satser](/grundlaggande/if-satser)                                 | [Konstruktorer](/klasser-och-objektorientering/kontruktorer)                                 | [Threading](/annat/threading)                                       |
| [Loopar](/grundlaggande/loopar)                                       | [Arv](/klasser-och-objektorientering/arv)                                                    |                                                                     |
| [Listor och arrayer](/grundlaggande/listor-och-arrayer)               | [Inkapsling och properties](/klasser-och-objektorientering/inkapsling-och-properties)        |                                                                     |
| [Slump](/grundlaggande/slump)                                         | [Static](/klasser-och-objektorientering/static)                                              |                                                                     |
| [String-manipulering](/grundlaggande/datatyper/string#string-metoder) | [Polymorfism](/klasser-och-objektorientering/polymorfism)                                    |                                                                     |
| [Egna metoder](/grundlaggande/metoder)                                | [Generiska klasser](/klasser-och-objektorientering/generiska-klasser)                        |                                                                     |
| [Använda bibliotek](/grundlaggande/anvaenda-bibliotek-using)          | [Läsa och skriva](/filhantering/laesa-och-skriva)                                            |                                                                     |
| [Namngivning](/grundlaggande/namngivning)                             | [Serialisering](/filhantering/serialisering)                                                 |                                                                     |
| [Begrepp](/grundlaggande/begrepp)                                     | [Nätverk och internet](/annat/naetverk-och-internet)                                         |                                                                     |
| [Pseudokod och diagram](/annat/pseudokod-och-diagram)                 |                                                                                              |                                                                     |


# Lathund: Skapa projekt

* Starta Visual Studio Code
* **SKAPA PROJEKTET**
  * Stäng nuvarande projekt: File → Close folder
  * Explorer → Create .NET Project (C# Dev Kit)
  * Välj "Console App"
  * Skapa och välj en mapp att skapa projektet i.
  * Välj ett namn på projektet.
    * Namnet bör vara i formen PlatformGame (inga mellanslag, stor bokstav i början av varje ord)
  * Om du får välja mellan "sln" eller "slnx", välj "sln"
  * Öppna csproj-filen och ta bort (eller kommentera bort) raden med `<Nullable>`.
* **GÖR SÅ PROJEKTET KAN KÖRAS**
  * Gå till "run and debug" (**Ctrl+Shift+D**, eller ikonen med play-knapp och insekt).
  * Tryck på "Run and Debug".
    * Eller tryck på **F5**
  * Välj "C#".
  * Välj "Launch startup project" och sedan projektets namn (bör vara enda i listan).
* **SKAPA GIT-REPOSITORY**
  * F1 → Add gitignore
    * Välj Visual Studio
  * Gå till Source Control
  * Initialize Repository
  * Skriv in ditt första commit-meddelande och stage:a alla filer du vill ha med (manuellt eller automatiskt)
  * Klicka på "Publish Branch".
  * Välj "Publish to GitHub **public** repository"
  * Om du behöver logga in eller göra något annat kommer VSCode att säga till. Följ instruktionerna.

(Test: [testlänk](/test))


# Lathund: koda i konsolen

<details>

<summary>Problem med svenska (eller t.ex. japanska) tecken i konsolen?</summary>

Ibland kan det vara problem med tecken i konsolen; de kanske skrivs ut som ? eller �. Om det är problem skriv följande kod i början av programmet.

```csharp
Console.InputEncoding = System.Text.Encoding.Unicode;
Console.OutputEncoding = System.Text.Encoding.Unicode;
```

</details>

## Kommentarer

Genom att skriva // framför något så gör man så det inte tolkas som kod utan som en kommentar.

```csharp
// Det här är en kommentar.
// Console.WriteLine("Det här är också en kommentar; en kod som inte körs");
```

## Variabler

Variabler lagrar information – allt man vill kunna komma ihåg i programmet lagras i variabler.

Varje variabel har en [**datatyp**](/grundlaggande/datatyper). När man skapar en variabel så anger man vilken sorts information som ska lagras i den.

```csharp
// int är datatypen, hp namnet på variabeln
int hp = 100;          // int = heltal
string name = "Micke"; // string = text
float money = 4.5f     // float = decimaltal
```

Man kan ändra på en variabels värde i efterhand. = funkar alltid, så länge variabeln är på vänster sida och det du vill ändra dess värde till är på höger.

```csharp
name = "Martin"; // Ändra name till 'Martin'
hp = hp + 10; // Öka hp med 10
hp += 5; // Öka hp med 5
hp++ // Öka hp med 1
hp-- // Minska hp med 1
```

## Läsa in data

### Läsa in text med [WriteLine](https://csharp.progdocs.se/pages/TzIIsQJlN4PczBnnXz5p#console.writeline), [ReadLine](https://csharp.progdocs.se/pages/TzIIsQJlN4PczBnnXz5p#console.readline)

Används för att skriva ut saker till användaren eller läsa in saker.

```csharp
Console.Write("Vad heter du? ");
string name = Console.ReadLine();
Console.WriteLine($"Hej {name}! Kul att du också är här :-)");  // Skriver ut 'Hej ...!  Kul att du också är här :-)
```

### Läsa in tal med [TryParse](https://csharp.progdocs.se/pages/-MHzQ4eGFcc-4IH2WYJF#int.tryparse)

Tryparse gör att man kan göra om en string till en int.

```csharp
string pointsText = Console.ReadLine();
int points = 0;
bool success = int.TryParse(pointsText, out points);
```

## Villkorssatser

### [If-else](/grundlaggande/if-satser)

If gör att man kan ha kod som bara körs om ett villkor stämmer (är *true*).

```csharp
string name = Console.ReadLine();
if (name == "Micke")
{
  Console.WriteLine("Välkommen!");
}
```

I exemplet nedan används också else if och else för att skapa en kedja.

```csharp
string name = Console.ReadLine();

if (name == "Micke") // Först kollas name mot 'Micke'
{
  Console.WriteLine("Välkommen!");
}
else if (name == "Martin")  // Om det inte är 'Micke' kollas namn mot 'Martin'
{
  Console.WriteLine("Hej!");
}
else  // och om det varken är 'Micke' eller 'Martin' körs den här koden
{
  Console.WriteLine("Dig känner jag inte, hejdå!");
}
```

### [Villkor](/grundlaggande/boolska-satser) och [jämförelser](/grundlaggande/operatorer#boolska)

Mellan parenteserna i if-satser och loopar skriver man någon form av jämförelse som blir sann eller falsk. Vanliga jämförelser kan vara:

* `==` "Är exakt lika med"
* `!=` "Är inte lika med"
* `>` "Är större än"
* `<` "Är mindre än"
* `<=` "Är större än eller lika med"
* `>=` "Är mindre än eller lika med

```csharp
int hp = 50;
if (hp < 10)
{
  Console.WriteLine("Skadad!");
}

if (hp > 100)
{
  Console.WriteLine("Overcharge!");
}
```

Man kombinerar ofta jämförelser med varandra, genom att använda && (och), || (eller).

```csharp
if (name == "Mikael" && pass == "password" && attempts < 4)
{
  Console.WriteLine("Välkommen!");
}
```

## [Slump](/grundlaggande/slump)

```csharp
// randomNumber blir ett tal som kan vara minst 0, max 99
int randomNumber = Random.Shared.Next(100);
// Talet kan vara minst 4, max 7
int otherNumber = Random.Shared.Next(4,7);
```

## Upprepa med loopar

### [While-loop](/grundlaggande/loopar#while-loop)

En loop när man inte vet hur många gånger koden skall köras.

```csharp
while (true) // Loop som körs för evigt
{
  string password = Console.ReadLine();
  if (password == "12345")
  {
    break; // Avbryter loopen
  }
}
```

En while-loop funkar exakt som en if-sats, utom att när koden som står under den är klar, så gör den jämförelsen igen – och om den fortfarande är *true* så kör den en gång till.

```csharp
string name = Console.ReadLine();
while (name != "Micke")
{
  name = Console.ReadLine()
}
```

**Observera** att exemplet ovan kan användas för alla möjliga jämförelser – så fort du vill begränsa användarens input, göra så att hen inte får gå vidare förrän hen skrivit in något som är "rätt sorts input", så kan du använda en while.

### [For-loop](/grundlaggande/loopar#for-loop)

En sorts loop som är väldigt bra när man vill köra en loop ett specifikt antal gånger. For-loopar funkar egentligen som while-loopar, men inkluderar en *räknare*.

```csharp
// Räknaren heter i, börjar på 0 och ökar med 1 varje gång loopen körts.
for (int i = 0; i < 10; i++) 
{
  // Det som står här inne kommer köras 10 gånger
  // Första gången loopen körs, har i värde 0
  // Andra gången har i värde 1
  // Tredje gången har i värde 2...
}
```

## [List](/grundlaggande/listor-och-arrayer#list)

Med listor kan man ha flera värden i samma variabel.

```csharp
List<int> numbers = [2, 45, 13, 200];
List<string> names = ["Micke", "Martin"];
```

Man kan läsa av och ändra på vad som finns på platser i en lista genom *indexering*. Varje plats i listan är numrerad från 0 och uppåt.

```csharp
List<string> names = ["Micke", "Martin"];
Console.WriteLine(names[0]); // Skriver ut 'Micke'
Console.WriteLine(names[1]); // Skriver ut 'Martin'
names[0] = "Mohammad"; // Byter ut 'Micke' mot 'Mohammad'
Console.WriteLine(names[0]); // Skriver ut 'Mohammad'
```

Man kan också kolla hur lång en lista är med Count, lägga till saker med Add och ta bort med Remove eller RemoveAt.

```csharp
List<string> names = ["Micke", "Martin"];
Console.WriteLine(names.Count); // Skriver ut '2'

names.Add("Jenny"); // Lägg till Jenny, som får index 2
names.Remove("Martin"); // Ta bort Martin, så att Jenny får index 1
names.RemoveAt(0); // Ta bort namnet med index 0

if (names.Contains("Jenny")) // Kolla om Jenny finns i listan
{
  Console.WriteLine("Jenny är med!");
}
```

Med en [foreach-loop](/grundlaggande/loopar#foreach-loop) kan man gå igenom listan och läsa av varje sak i den i tur och ordning.

```csharp
foreach (string name in names) // Loopa igenom listan
{
  Console.WriteLine(name);
}
```

## [Metoder](/grundlaggande/metoder#enkel-metod)

En metod är en bit återanvändbar kod, som kan anropas från andra delar av koden. Metoder som är statiska är helt separata från resten av koden – de kan inte komma åt variabler som inte är deras egna. Metoder är överlag lite som Las Vegas: Det som händer i metoden stannar i metoden. Om man inte specifikt säger något annat.

```csharp
static void CountDown()
{
  for (int i=10; i>0; i--)
  {
    Console.WriteLine(i + "...");
  }
}
```

### Parametrar

För att få *in* data i en metod används parametrar. Det gör man generellt när man vill att en och samma metod ska kunna göra delvis olika saker beroende på vilken data den ges.

```csharp
static void CountDownFrom(int startValue)
{
  for (int i=startValue; i>0; i--)
  {
    Console.WriteLine(i + "...");
  }
}

CountDownFrom(100); // 100 stoppas in i parametervariabeln startValue
CountDownFrom(10);
```

### Returnering

Om man vill ta med sig något från inifrån en metod så använder man *return*.

```csharp
// 'string' betyder att vi lovar att metoden returnerar en string
//        ↓
static string GetName() 
{
  string name = "";
  while (name.Length == 0)
  {
    Console.WriteLine("Vad heter du?");
    name = Console.ReadLine();
  }
  
  return name; // 'return' avslutar metoden och skickar tillbaka innehållet i 'name'
}

string heroName = GetName();
string enemyName = GetName();
```

## Klasser

Varje klass läggs normalt i en egen fil.

{% code title="Enemy.cs" %}

```csharp
class Enemy
{
  public string Name;
}
```

{% endcode %}


# Lathund: koda WPF-applikationer

## Appens fönster

```xml
<Window ...
        Title="MinApp"
        MaxWidth="800" MaxHeight="450"
        SizeToContent="WidthAndHeight">
    <!-- Innehållet i fönstret -->
</Window>
```

## Vanliga kontroller och attribut i XAML

### Layoutkontroller – StackPanel

En layoutkontroll som ordnar sina barnkontroller i en vertikal eller horisontell stapel.

```xml
    <StackPanel Background="#EEE" Orientation="Horizontal">
        <!-- Barnkontroller -->
    </StackPanel>
```

### Vanliga kontroller

```xml
<Label Margin="10" FontSize="24" Foreground="#FFF">Ange ditt namn</Label>
<Button Margin="10" Padding="10" Background="Red" FontWeight="Bold" Width="100">Spara</Button>
<TextBox Margin="10" Padding="10" Height="100"></TextBox>
<ListBox Margin="10" Padding="10"></ListBox>
```

Andra användbara attribut för `TextBox`-kontrollen:

* `ReadOnly="True"` – gör textfältet skrivskyddat
* `TextWrapping="Wrap"` – gör att texten bryts om den är för lång för att få plats i fältet
* `AcceptsReturn="True"` – gör att användaren kan trycka på Enter för att skapa en ny rad

## Koppla kontroller till C#-kod

### click-event och event-metoder

När en användare klickar på en knapp utlöses ett `click`-event.

```xml
<Button Click="KlickSpara" Margin="10" Padding="10">Spara</Button>
```

```csharp
void KlickSpara(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Du sparade dina ändringar!");
}
```

### Referens till kontroller: Name-attributet

Med `Name`-attributet kan vi referera till kontroller i C#-koden:

```xml
<TextBox Name="txbResultat" Margin="10" Padding="10"></TextBox>
```

```csharp
// Läs innehållet i textfältet
string innehall = txbResultat.Text;

// Sätt nytt innehåll i textfältet
txbResultat.Text = "Nytt innehåll visas här!";
```

### Visa en list i en ListBox

Innehållet i en lista kan visas i en `ListBox`-kontroll:

```xml
<ListBox Name="lbResultat" Margin="10" Padding="10"></ListBox>
```

```csharp
List<string> namnLista =["Anna", "Bertil", "Cecilia"];

// Sätt listan som källa för ListBox-kontrollen
lbResultat.ItemsSource = namnLista;

// Uppdatera ListBox-kontrollen med ny data
lbResultat.Items.Refresh();
```


# Kompilering och publicering

## Kompilering och debug-körning

Medan du arbetar med projektet så skapar du s.k. "debug builds", särskilda versioner av programmets exe- och dll-filer som fungerar bra ihop med vscode och dess olika verktyg.

Genom att trycka F5 skapas en mapp som heter "bin", och i den finns en mapp som heter "Debug". Där finns ytterligare en undermapp som heter "net8.0" (om du använder .NET SDK 8). I den mappen läggs dina tillfälliga debug builds.

Så snart .net skapat din debug build så körs den, så normalt märker du inte ens att det blir exe- eller dll-filer – du ser bara koden, och sedan att programmet körs.

## Publicering

För att skapa en version av ditt program som är lämpligt att distribuera till andra, gå till terminalen i Visual Studio Code (eller någon annan terminal; se till att vara i samma mapp som SLN-filen).

Skriv detta, och tryck enter:

```
dotnet publish -c Release
```

Resultatet bör se ut ungefär såhär:

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHmNgpRz-b16wpwGwZI%2F-MOC6ovxevlvScTzFcVw%2F-MOC7hQBfWt1i16-O5FI%2Fimage.png?alt=media\&token=1c2ad6df-ae16-4460-8c26-8fec8f19cb40)

I ditt projekt bör du nu ha en mapp som heter "bin" och i den finns en mapp som heter "Release". Där finns ytterligare en undermapp som heter "net8.0" (om du använder .NET Core 8), och under den finns en som heter "publish". Filerna i publish-mappen är de du kan distribuera till andra.

<img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHmNgpRz-b16wpwGwZI%2F-MOC6ovxevlvScTzFcVw%2F-MOC8Pz4sMDv1cMAE76C%2Fimage.png?alt=media&amp;token=a2c5985e-88da-4dbb-8da7-b10702e61fd5" alt="" data-size="original">&#x20;

### En ensam exe-fil

För att packa ihop ovanstående till en ensam exe-fil du kan distribuera behöver du bli mer specifik:

```powershell
dotnet publish -r win-x64 -c Release -p:PublishSingleFile=true --self-contained false
```

Här behöver mottagaren fortfarande ha dotnet installerat – inte SDK nödvändigtvis, men runtime. Det borde dock inte vara något större problem då dotnet 8 brukar vara installerat i de flesta moderna windowsversioner.

### Överkurs: standalone

Vill man ha en exe-fil som inte kräver att man har .NET Core 8 installerat, så kan skriva man såhär när man publicerar (om det nu är windows 10 64-bitarsversionen man bygger till):

```markup
dotnet publish -r win-x64 -c Release -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained true
```

Då kommer filerna i publish-mappen fortfarande vara ganska få, men exe-filen kommer att vara betydligt större. Mappstrukturen blir också lite annorlunda, men det bör inte vara svårt att hitta rätt filer att publicera.

Vill man verkligen bara ha *en* exe-fil så kan man lägga till ytterligare en parameter:

```markup
dotnet publish -r win-x64 -c Release -p:PublishSingleFile=true -p:PublishTrimmed=true -p:IncludeNativeLibrariesForSelfExtract=true --self-contained true
```


# Externa resurser

## Onlinekurser

**På svenska**

* **Csharpskolan:** <https://www.youtube.com/playlist?list=PLGIaaBeLgSj-gR2ce4llrGt9c_1J7JqoC>
* **Distansakademin C#:** <https://www.youtube.com/playlist?list=PLI5JF23TK_8CB6bhsiRski3W3PCFqVltx>

**På engelska**

* **FreeCodeCamp – Microsoft C#:** <https://www.freecodecamp.org/learn/foundational-c-sharp-with-microsoft/>
* **Code Academy:** <https://www.codecademy.com/catalog/language/c-sharp>
* **Brackeys C#:** <https://www.youtube.com/playlist?list=PLPV2KyIb3jR4CtEelGPsmPzlvP7ISPYzR>


# Datatyper \[…]

## int

Integer, heltal.

```csharp
int x = 3;
```

Man kan använda understreck för att göra heltalen mer lättlästa.

```csharp
int million = 1_000_000;
```

## string

En string är en text – en serie tecken efter varandra.

```csharp
string s = "Hello";
```

[Mer om strings finns här](/grundlaggande/datatyper/string)

## float

Flyttal, decimaltal.

```csharp
float y = 3.4692f;

Console.WriteLine(y:N2); // Skriver ut talet med 2 decimaler
```

## double

Decimaltal som kan innehålla större tal – dubbelt så stora som floats.

```csharp
double x = 7.892;

Console.WriteLine(x:N2); // Skriver ut talet med 2 decimaler
```

## bool

Ett booleskt värde, är antingen true eller false.

```csharp
bool z = true;
```

## char

Ett tecken.

```csharp
char c = 'ä';
```

### Char.Is…

I klassen Char finns flera metoder för att undersöka char-tecken. Till exempel:

```csharp
Char.IsDigit(c) // true om c är en siffra
Char.IsLetter(c) // true om c är en bokstav
Char.IsLetterOrDigit(c) // true om c är en siffra eller en bokstav
Char.IsUpper(c) // true om c är en STOR BOKSTAV
Char.IsWhiteSpace(c) // true om c är ett mellanslag, en tabb eller en radbrytning
```

Observera att definitionen av "siffra" här inte bara inkluderar tecknen 0–9 utan också till exempel thailändska siffertecken.

## Andra heltal

Överkurs: det finns ett antal olika sätt att spara heltal, och de har olika min- och maxvärden.

* **int**, eller int32, är en 32-bitars integer. Den använder 32 ettor och nollor (bits/bitar) för att lagra ett heltal som kan vara positivt eller negativt. En av bitarna används för att avgöra ifall talet är positivt eller negativt.
* **long**, eller int64, är en 64-bitars integer.
* **short**, eller int16, är en 16-bitars integer.
* **uint**, **ulong** och **ushort** är versioner av int, long och short som inte kan bli negativa – men i gengäld kan mäta större positiva tal. Eftersom ingen bit används för att avgöra om talet är positivt/negativt.

Vilken som är lämplig vid vilket tillfälle beror på hur höga tal man behöver lagra samt hur viktigt det är att spara på minnesutrymmet.

```csharp
Console.WriteLine(int.MaxValue); //   2147483647
Console.WriteLine(int.MinValue); //  -2147483648
Console.WriteLine(uint.MaxValue); // 4294967295
Console.WriteLine(uint.MinValue); // 0

Console.WriteLine(long.MaxValue); //   9223372036854775807
Console.WriteLine(long.MinValue); //  -9223372036854775808
Console.WriteLine(ulong.MaxValue); // 18446744073709551615
Console.WriteLine(ulong.MinValue); // 0

Console.WriteLine(short.MaxValue); // 32767
Console.WriteLine(short.MinValue); // -32768
Console.WriteLine(ushort.MaxValue); // 65535
Console.WriteLine(ushort.MinValue); // 0
```

## Void

Void är egentligen inte en datatyp – det är mer ett ord som används när man specifikt inte förväntar sig någon data. Void används bara som returdatatyp för [metoder ](/grundlaggande/metoder)som inte ska returnera något.

## Null

Null är inte heller riktigt en datatyp, utan snarare "icke-data". En string-variabel som ges värdet null är inte ens en tom string – det är ett icke-värde.


# String

En string är en text – en serie tecken efter varandra.

```csharp
string s = "Hello";
```

## $ – interpolation

Om man skriver $ framför en string, så kan man sedan stoppa in variabler och metodanrop och annat inuti måsvingar i stringen. Det som står innanför måsvingarna *utvärderas* och blir en del av stringen.

```csharp
int hp = 100;
string s = $"Du har {hp} hit points kvar";
```

Om man har ett decimaltal ([float](/grundlaggande/datatyper#float) eller [double](/grundlaggande/datatyper#double)) så kan man skriva : och sedan ett format med t.ex. antal decimaler.

```csharp
float c = 23;
float f = 32 + (c * 1.8f);
Console.WriteLine($"Fahrenheit: {f:00.00}");
```

## ToLower()

En metod som är inbyggd i alla strings, och ger en kopia av stringen där alla stora bokstäver bytts ut mot små.

```csharp
string name = "Micke";
string nameSmall = name.ToLower(); // värdet i nameSmall blir "micke".
```

Detta är praktiskt när man t.ex. vill göra jämförelser och det inte ska spela någon roll ifall användaren skriver med stor bokstav.

## Length

Length är en egenskap alla strings har. Det är en int som innehåller det antal tecken stringen har.

```csharp
Console.WriteLine($"Texten {s} har {s.Length} tecken");
```

## `\` – specialtecken

Om man skriver `\` i en string så kommer tecknet efter att tolkas som ett specialtecken. Det vanligaste är `\n`, som är en newline (ny rad).

```csharp
Console.WriteLine("Detta är första raden.\nDetta är andra raden.");
```

## `"""` – raw strings

Väldigt praktiskt för ASCII-art och andra strings som har flera rader.

Om man använder tre citattecken före och efter en string:

* Alla tecken inklusive `"` och `\` tolkas som vanliga tecken snarare än kommandon.
* Framför allt den avslutande `"""` måste vara på en egen ny rad
* Ingen rad i stringen får börja längre åt vänster än den avslutande `"""`.
* Indraget för sista """ anger var alla raderna anses "börja", så även om hela stringen har ett indrag på 8 mellanslag så kommer den skrivas ut med 2 mellanslags indrag om den avslutande """ är indragen 6 mellanslag.
* Man kan fortfarande använda `$` och `{}` för att infoga variabler.

```csharp
Console.WriteLine("""
          _  .   .   .
        .' '; '-' '-'|-.
      (     '------.'  )
        ;            \ /
        :     '   ' |/
        '._._       \    .;
        .-'   ;--.    '--' /
      /      \-'---.___.'
      |     / 7 \(>o<) /\
      |     | \ |  . \   \
      |=====|   |  .  \ |-)
      |-'-'   ./_.-._.\|"
      '-.----'        |
        |       |     |
        |     | |   | |
        |_____|_|___|_|
        (-------',----'.
          '-'-----'-----'         
    """);
```

## `@` – verbatim strings

Om man skriver @ framför en string, så kommer varje tecken i denna string sedan att tolkas väldigt bokstavligt. Framför allt används detta när man inte vill att \ ska tolkas, utan bara skrivas ut som just \\. Det är praktiskt när man ska göra sökvägar i Windows.

```csharp
Console.WriteLine(@"Detta är första raden.\nDetta är också första rader.");
```

## String-metoder

### Replace()

Byter ut ett tecken eller en del-string.

{% code lineNumbers="true" %}

```csharp
string oldString = "Mikael är min programmeringslärare";

string newString = oldString.Replace("Mikael", "Micke");
```

{% endcode %}

### Substring()

Returnerar en del av stringen. Tar emot startposition och längd som parametrar. Anges bara en parameter så antas längden vara resten av stringen.

{% code lineNumbers="true" %}

```csharp
string oldstring = "Detta är en string";

string sub1 = oldString.Substring(2,5); // sub1 blir "tta ä"

string sub2 = oldString.Substring(2); // sub2 blir "tta är en string"
```

{% endcode %}

### Trim()

Returnerar en kopia av stringen där mellanslag och andra "tomma" tecken tagits bort från början och slutet.

```csharp
string clean = oldString.Trim();
```

Det finns också `TrimEnd` och `TrimStart` ifall man bara vill trimma slutet eller början av stringen.

### Insert()

Returnerar en kopia av stringen där en annan string stoppats in på en angiven plats. Tar emot en position och en string som parametrar.

{% code lineNumbers="true" %}

```csharp
string folk = "micke och kim och mimmi";

string nyFolk = folk.insert(5, " och herbert"); 
// nyFolk blir "micke och herbert och kim och mimmi"
```

{% endcode %}

### Contains()

Kollar om en string innehåller en annan string, t.ex. ifall "haj" finns i texten "en haj hoppar över en björn". Returnerar true om den finns, false om den inte gör det.

{% code lineNumbers="true" %}

```csharp
string answer = Console.ReadLine();
bool hasAShark = answer.Contains("haj");

if (hasAShark == true)
{
  Console.WriteLine("Du skrev något med ordet haj!");
}
```

{% endcode %}

### IndexOf()

Returnerar positionen för den första plats i stringen där en annan string finns. Tar emot något att söka efter som parameter.

{% code lineNumbers="true" %}

```csharp
string folk = "micke och kim och mimmi";
int kimPlats = folk.IndexOf("kim");
int mellanslagPlats = folk.IndexOf(" ");
```

{% endcode %}

Resultatet av ovanstående blir att variabeln kimPlats får värdet 10 och att mellanslagPlats får värdet 5. Positionssiffrorna börjar på 0.

### ToUpper()

Returnerar en kopia av stringen där alla gemener (små bokstäver) bytts ut mot versaler (stora bokstäver).

```csharp
string caps = oldString.ToUpper();
```

### ToLower()

Returnerar en kopia av stringen där alla versaler (stora bokstäver) bytts ut mot gemener (små bokstäver).

```csharp
string small = oldString.ToLower();
```

Denna används ofta för att till exempel förvandla strings man fått in från en användare så att det inte spelar någon roll ifall hen svarat t.ex. JA, Ja, jA eller ja.

### Sätta ihop och ta isär

#### String.Join()

Sätter ihop alla element i en array till en string. Tar emot två parametrar; en separator som placeras mellan elementen och en array med de element som ska sättas ihop.

{% code lineNumbers="true" %}

```csharp
string[] names = {"micke", "kim", "mimmi"};
string folk = String.Join(" och ", names);

// Variabeln "folk" får namnet "micke och kim och mimmi"
```

{% endcode %}

#### Split()

Returnerar en array som består av en uppdelad string. Tar emot en separator som parameter. Separatorn kan bara vara ett ensamt tecken, en **char**.

{% code lineNumbers="true" %}

```csharp
string folk = "micke och kim och mimmi";
string[] names = folk.Split(' ');

// Variabeln "names" får innehållet {"micke", "och", "kim", "och", "mimmi"}
```

{% endcode %}

## En string är en array

I grunden är en string helt enkelt en [array ](/grundlaggande/listor-och-arrayer#array)av [chars](/grundlaggande/datatyper#char). Det betyder att man kan använda alla tekniker man normalt kan med arrayer – Length, indexering och ranges till exempel – även med strings

{% code lineNumbers="true" %}

```csharp
string name = "Mikael Bergström";

char firstChar = name[0]; // firstChar blir M

string firstPart = name[..6]; // firstPart blir "Mikael"
```

{% endcode %}

## All()

All() är en del av **Linq-biblioteket** så man måste först ha med `using System.Linq`. All har en [delegate ](/grundlaggande/delegates)som parameter, och förväntar sig då en metod (eller ett lambda-uttryck) som tar emot en `char` och returnerar `true` eller `false`. All stoppar sedan i var och ett av stringens tecken in i den angivna metoden. Om resultatet för alla blir `true` så returnerar All också `true`.

```csharp
using System.Linq;

string s1 = "12345";
string s2 = "123a45;

bool b1 = s1.All(char.IsDigit); // b1 = true
bool b2 = s2.All(char.IsDigit); // b2 = false
```


# Tuples

Tuples är ett sätt att lagra flera bitar information i samma variabel.

Datatypen för variabeln anges då som en parentes, och i den parentesen skriver man datatyperna som ska ingå, i ordning.

```csharp
(int, int) coordinate = (3, 4);

(string, int) property = ("strength", 10);
```

När man gör som i exemplen ovan så får varje egenskap ett automatiskt namn, utifrån modellen item#, där # är numret i ordningen för den datan.

Så för att få ut trean ur koordinaten skulle man skriva:

```csharp
Console.WriteLine(coordinate.item1);
```

Och för att få fram värdet 10 så skulle man skriva:

```csharp
Console.WriteLine(property.item2);
```

Observera alltså att namngivningen börjar på 1 och inte 0!

## Namnge en tuples egenskaper

Man kan ge egenskaperna namn, som man då bestämmer när man skapar datatypen.

```csharp
(int x, int y) coordinates = (3, 4);
Console.WriteLine(coordinates.x);
```

## Tuples i arrayer och listor

```csharp
(int x, int y)[] coordinateArray = new (int, int)[10];
List<(int x, int y)> coordinateList = new List<(int, int)>();
```

## Tuples som returtyp

```csharp
static (int x, int y) GetCoordinates()
{
  return (5, 6)
}
```

## Tuples som parameter

```csharp
static void ReceiveCoordinate((int x, int y) coord)
{
  Console.WriteLine(coord.x);
}
```


# Enum

Enums är ett snabbt, enkelt sätt att skapa egna "datatyper".

Man skriver dem **utanför de vanliga metoderna**.

När man skapar en enum, så bestämmer man vilka värden som ska vara giltiga – ungefär som att de enda giltiga värdena för en boolean är true och false.

```csharp
Enum Room {
  entrance,
  corridor,
  dungeon
}
```

I exemplet är de enda giltiga värdena för en variabel med Rooms-datatypen entrance, corridor och dungeon.

Senare, i metoderna, kan de användas som datatyper.

Man skapar alltså variabler där man anger datatypen som enum-namnet:

```
Room currentRoom = Room.entrance;
```

Man kan också använda dem i till exempel if-satser:

```csharp
if (currentRoom == Room.corridor)
{
  // kod
}
```

Vill man skapa mer komplexa egna datatyper så är det [klasser](https://sites.google.com/view/csharp-referens/klasser-och-objektorientering?authuser=0) som gäller.


# Fel

## Syntaxfel

Ett syntaxfel är ett fel i själva grammatiken i koden; ett ganska lättfångat fel där man helt enkelt skrivit något ogiltigt. Syntaxfel signaleras i Visual Studio Code genom att strykas under med röda vågiga streck, s.k, "sqiggley lines". Man kan också få fram en lista med alla syntaxfel genom att gå till Problems-panelen (View → Problems).

## Runtime-fel (exceptions)

Ett runtime-fel är ett fel som uppstår när programmet körs. Koden som orsakar felet är syntaxmässigt korrekt, men den operation som koden beskriver går inte att utföra. Det kan till exempel vara att man försöker komma åt en position i en array som inte finns.

```csharp
int[] numbers = {3, 4, 12, 66};
Console.WriteLine(numbers[8]); // Det finns ingen åttonde int i arrayen
```

När ett runtime-fel uppstår så skapas ett Exception. Detta kan fångas upp av en [try-catch](/grundlaggande/try-catch).

## Logiska fel

Logiska fel är de svåraste att hitta – de hittas inte av Visual Studio (inga röda sqiggley lines), de orsakar inga felmeddelanden. De är helt enkelt resultatet av ett feltänk hos programmeraren – som leder till oönskat beteende.

```csharp
// Eftersom || används istället för && så räcker det med att ha rätt
//  användarnamn ELLER rätt lösenord.

if (username == "micke || password == "12345")
{
  loggedIn = true;
}
```


# Typkonvertering

## Implicit konvertering

En del datatyper kan lätt konverteras till andra utan att man behöver göra någon manuell konvertering. Det gäller framför allt när konverteringen inte innebär att man blir av med information eller precision.

{% code lineNumbers="true" %}

```csharp
int i = 9;
long l = i;
```

{% endcode %}

### Exempel:

* int → long
* int → string
* int → float
* float → double

## Casting

När konverteringen innebär att man blir av med precision, t.ex. går från en float till en int och blir av med decimaler, så använder man ibland **casting**. Det betyder att man helt enkelt skriver vilken datatyp man vill konvertera till inom parenteser innan värdet som ska konverteras.

{% code lineNumbers="true" %}

```csharp
float xPos = 3.4f;
int x = (int) xPos;
```

{% endcode %}

## As

As fyller en liknande funktion som casting, men fungerar bara på datatyper som är av referenstyp (t.ex. klasser) och datatyper som kan bli null (t.ex. string). Detta är mest användbart när man använt [polymorfi](/klasser-och-objektorientering/polymorfism).

As går också lite snabbare än casting.

{% code lineNumbers="true" %}

```csharp
// Säger att instansen som enemy-variabeln pekar mot är en instans av Goomba,
//  och att Goomba-variabeln "g" också ska peka mot samma instans.
Goomba g = enemy as Goomba;
```

{% endcode %}

## Is

Is kan användas för att se vilken datatyp ett värde är. Detta är mest användbart när man använt [polymorfi](/klasser-och-objektorientering/polymorfism).

{% code lineNumbers="true" %}

```csharp
// Om instansen som enemy-variabeln pekar mot är en instans av Goomba-klassen,
//  så kör koden inuti if-blocket.

if (enemy is Goomba)
{
  // ---
}
```

{% endcode %}

Is kan också göra en samtidig As-operation.

{% code lineNumbers="true" %}

```csharp
// Om instansen som enemy-variabeln pekar mot är en instans av Goomba-klassen
//  så skapa en ny variabel "g" som är an datatypen Goomba och pekar mot
//  samma instans.

if (enemy is Goomba g)
{
  g.SetColor("Brown");
}
```

{% endcode %}

## Konvertera till int

### int.Parse()

Många datatyper kan inte konverteras direkt till t.ex. en int. Metoden int.Parse tar emot nästan vad som helst – t.ex. en string – och försöker konvertera den till en int.

{% code lineNumbers="true" %}

```csharp
string tal = "42";
int i = int.Parse(tal);
```

{% endcode %}

{% hint style="warning" %}
**OBS:** Parse kommer att orsaka ett runtime error ifall den string som anges inte kan konverteras till en int. Använd [try-catch](/grundlaggande/try-catch) för att fånga upp felet eller använd TryParse istället för Parse.
{% endhint %}

### int.TryParse()

För en enkel, säker konvertering kan man använda TryParse.

{% code lineNumbers="true" %}

```csharp
string tal = "42";
int resultat;
bool lyckad = int.TryParse(tal, out resultat);
```

{% endcode %}

TryParse returnerar true om konverteringen lyckades, false om den inte lyckades. Resultatet lagras i variabeln som anges som "out"-variabel i den andra parametern (i exemplet, variabeln "resultat"). Om konverteringen misslyckas så blir resultatet 0.

## Konvertera till float

### float.Parse()

Tar emot ett värde, och konverterar det till en float – om det går. Resultatet av konverteringen returneras.

{% code lineNumbers="true" %}

```csharp
string tal = "42.5"
float f = float.Parse(tal);
```

{% endcode %}

Om det inte går att konvertera värdet till en float, kommer Parse att ge ifrån sig ett runtime-felmeddelande.

### float.TryParse()

För en enkel, säker konvertering kan man använda TryParse.

{% code lineNumbers="true" %}

```csharp
string tal = "42.5";
float f;
bool lyckad = float.TryParse(tal, out f);
```

{% endcode %}

TryParse returnerar true om konverteringen lyckades, false om den inte lyckades. Resultatet lagras i variabeln som anges som "out"-variabel i den andra parametern (i exemplet, variabeln "resultat"). Om konverteringen misslyckas så blir resultatet 0.


# Operatorer

## Matematiska

### + Addition och konkatenering

{% code lineNumbers="true" %}

```csharp
int x = 4 + 6; // Addition
string s = "hej " + "då" // Konkatenering
string s2 = "Värdet på x är " + x;
```

{% endcode %}

### - Subtraktion.

```csharp
int x = 6 - 4;
```

### / Division.

```csharp
int x = 6 / 3;
```

OBS: Om man delar ett heltal (int eller long) med ett annat heltal blir resultatet alltid ett heltal – decimaler trunkeras bort.

### \* Multiplikation.

```csharp
int x = 2 * 3;
```

### % Modulus

Räknar ut resten.

```csharp
int x = 5 % 2;
```

x blir lika med 1, eftersom det är vad man får kvar när man delat 5 med 2.

## Tilldelning

### = Tilldela ett värde till en variabel

```csharp
i = 6;
```

### += Addera något till variabelns värde.

```csharp
i += 5;
```

### ++ Lägg till 1 till variabelns värde.

```csharp
i++;
```

### -= Subtrahera något från variabelns värde.

```csharp
i -= 5; 
```

### -- Dra ifrån 1 från variabelns värde.

```csharp
i--;
```

## Boolska

### == Lika med

Är operanderna **likadana**?

```csharp
bool x = 4 == 4; // true eftersom 4 är samma som 4
```

### != Inte lika med

Är operanderna **olika**?

```csharp
bool x = 4 != 5; // true eftersom det stämmer att 4 och 5 är olika
```

### > < Större än, mindre än.

```csharp
bool x = 4 > 3;
```

### <= >= Större än eller lika med, Mindre än eller lika med

```csharp
bool x = 4 >= 4; // Blir true eftersom fyra är större än eller lika med fyra

bool y = 3 <= 10;
```

## Logiska

### && And (Och)

True om **båda** operanderna är true, dvs det är true på båda sidorna om &&.

```csharp
bool x = true && true; // resultatet är true
```

```csharp
bool y = true && false; // resultatet är false
```

### || Or (Eller)

True om **minst en** av operanderna är true.

```csharp
bool x = true || false; // true; det räcker om den ena är true.
bool y = false || false; // false
bool z = (3 == 2) || x; // true; x är true även om 3 inte är samma som 2.
```

## Specialoperatorer

### . Member access

Används för att komma åt variabler och metoder som ingår i andra objekt. Varje string har till exempel en inbyggd egenskap, en "medlem", som heter Length.

```csharp
string s = "Hello";
Console.WriteLine(s.Length); // 5
Console.WriteLine("Worlds".Length); // 6
```

### .? Null conditional

Används precis som Member access-operatorn men gör att man inte får ett [runtime-fel](/grundlaggande/fel#runtime-fel-exceptions) ifall objektet är null.

```csharp
string s = null;
Console.WriteLine("Längd: " + s?.Length); // Längd: 
Console.WriteLine("Längd: " + s.Length); // Runtime-fel
```

### ? : Ternary

Ternary-operatorn fungerar som en förkortad if-sats och består av tre delar – ett villkor, ett värde som gäller ifall villkoret är sant och ett värde som gäller ifall villkoret är falskt.

```csharp
int i = 1;

// Om i == 1 så blir name lika med "Micke", annars blir name lika med "Mira".
string name = i == 1 ? "Micke" : "Mira";
```

### ?? Null-coalescing

Null-coalescing-operatorn används när det finns en risk för att ett värde är null, och gör så att ett alternativt värde kan tilldelas.

```csharp
// actualName får samma värde som name, förutsatt att name inte är null.
// om name är null så blir actualName "Micke" istället.
string actualName = name ?? "Micke";
```


# Boolska satser

En boolsk sats är en formel som resulterar i antingen ett sant eller ett falskt värde – ett [bool](/grundlaggande/datatyper#bool)-värde.

```csharp
int i = Random.Shared.Next(10);

// Den boolska satsen blir true om i är högre än 2 och samtidigt lägre än 8.
// Resultatet av den boolska satsen sparas i result
bool result = i > 2 && i < 8;
```

Man kan inkludera allt möjligt – jämförelser med [boolska ](/grundlaggande/operatorer#boolska)och [logiska ](/grundlaggande/operatorer#logiska)operatorer, bool-variabler, metoder som returnerar boolska värden.

```csharp
bool jumpThisFrame = IsGrounded() && hasReleasedJumpButton && jumpCharge > 0;
```

Boolska satser används ofta i if-satser, while-loopar och liknande för att *göra flera jämförelser samtidigt*.

```csharp
int r = Random.Shared.Next(10);

while (r < 2 || r > 8)
{
  Console.WriteLine($"Sorry, fick en {r} så jag är fast i loopen en stund till");
}
```

Det är en teknik som ofta används som del av när man vill [begränsa input](/tekniker-och-designmonster/begraensa-input) för användaren


# Konsolen (Console)

<details>

<summary>Problem med svenska (eller t.ex. japanska) tecken i konsolen?</summary>

Ibland kan det vara problem med tecken i konsolen; de kanske skrivs ut som ? eller �. Om det är problem skriv följande kod i början av programmet.

```csharp
Console.OutputEncoding = System.Text.Encoding.Unicode;
Console.InputEncoding = System.Text.Encoding.Unicode;
```

</details>

## Skriva ut och läsa in text

### Console.WriteLine()

Skriver ut något till konsolen, med en radbrytning i slutet.

```csharp
Console.WriteLine("Hello!");
```

### Console.Write()

Skriver ut något till konsolen, utan radbrytning efteråt.

```csharp
Console.Write("Hello");
Console.Write("World");
```

### Console.Clear()

Rensar skärmen.

```csharp
Console.Clear();
```

### Console.ReadLine()

Läser in en string från användaren och väntar på Enter-tryckning. Returnerar stringen så att den kan lagras i en variabel eller användas i koden.

```csharp
string answer = Console.ReadLine();
```

### Console.ReadKey()

Läser in ett knapptryck från användaren. Pausar körningen av programmet tills en knapptryckning sker.

```csharp
ConsoleKey key = Console.ReadKey();
```

### Console.KeyAvailable

Kollar om en knapptryckning skett sedan förra gången ReadLine eller ReadKey kördes. Praktisk för när man t.ex. inte vill att körningen av programmet ska pausas när man kör en ReadKey().

```csharp
if (Console.KeyAvailable)
{
  ConsoleKey key = Console.ReadKey();
}
```

### Console.OutputEncoding

Ändrar vilken teckenkodning som ska användas när saker skrivs ut till konsolen.

```csharp
Console.OutputEncoding = System.Text.Encoding.UTF8;
```

Med UTF-8 som teckenkodning kan man använda fler tecken – till exempel emojis som 🤖.

```csharp
Console.WriteLine("🤖");
```

## Färg

### Console.ForegroundColor

Variabel vars värde avgör färgen på texten i konsolfönstret.

```csharp
Console.ForegroundColor = ConsoleColor.Cyan;
```

{% hint style="warning" %}
**OBSERVERA:** detta gäller enbart text som skrivs *efter* det att färgen ändrats. Text som redan skrivits ut förändras inte.
{% endhint %}

### Console.BackgroundColor

Variabel vars värde avgör färgen på texten i konsolfönstret.

```csharp
Console.BackgroundColor = ConsoleColor.Magenta;
```

{% hint style="warning" %}
**OBSERVERA:** detta gäller enbart text som skrivs efter det att färgen ändrats. Text som redan skrivits ut förändras inte. Man kan använda Console.Clear() för att fylla skärmen med den nya bakgrundsfärgen.
{% endhint %}

### Console.ResetColor

Återställer för- och bakgrundsfärg till konsolens vanliga.

```csharp
Console.ResetColor();
```

### ANSI-färger

ANSI är en gammal textstandard, med koder som fortfarande kan användas för att formatera text i konsolen. Man börjar varje kommando med `\x1b[`, följt av en siffra och sedan `m`. [En komplett lista finns här](https://gist.github.com/raghav4/48716264a0f426cf95e4342c21ada8e7).

I exemplet nedan används alltså `\x1b[34m` för att aktivera blå färg, och sedan används `\x1b[0m` för att återgå till normal färg.

```csharp
Console.WriteLine("\x1b[34mBlå\x1b[0m färg");
```

## Fönstret

### Console.Title

Ändrar konsolfönstrets namn.

```csharp
Console.Title = "Mitt fina fönster";
```

## Console.Beep()

Gör ett ljud!

```csharp
Console.Beep(294,1000) // 1 sekunds (1000 millisekunders) beep i D.
```

## Pekaren

### Console.SetCursorPosition()

Bestäm pekarens position i x- och y-led. Tar emot två int-värden.

```csharp
Console.SetCursorPosition(20, 10); // Plancera pekaren på column 20, rad 10
```

{% hint style="warning" %}
**OBSERVERA:** y-axeln är **omvänd**! Med andra ord, den första raden är 0, den andra är 1, den tredje är 2… Och "origo" ligger uppe i vänstra hörnet.
{% endhint %}

### Console.GetCursorPosition()

Läs av pekarens position i x- och y-led. Returnerar en [tuple ](/grundlaggande/datatyper/tuples)där det första värdet är x, det andra y.

```csharp
(int x, int y) = Console.GetCursorPosition();
```

### Console.CursorLeft

Pekarens position i x-led, räknat från fönstrets vänstra kant (den första "kolumnen" är 0)

```csharp
Console.CursorLeft = 20; // Placera pekaren i kolumn 20
Console.CursorLeft -= 5; // Flytta pekaren fem steg åt vänster
```

### Console.CursorTop

Pekarens position i y-led, räknat från fönstrets överdel.

```csharp
Console.CursorTop = 10; // Placera pekaren på rad 10
Console.CursorTop-- // Flytta pekaren 1 rad uppåt
```


# If-satser

## if-sats

Ett villkorat kodblock. Koden i blocket körs bara om det som är mellan parenteserna är *sant*.

Man kan bara lägga in kod som ger [boolskt](/grundlaggande/datatyper#bool) resultat mellan parenteserna, t.ex. en [jämförelse ](/grundlaggande/operatorer#boolska)eller en metod som [returnerar ](/grundlaggande/metoder#returnering)ett boolskt värde.

{% code lineNumbers="true" %}

```csharp
if (i > 4)
{
  Console.WriteLine("Högre än fyra!");
}

if (name == "Micke")
{
  Console.WriteLine("Innehållet i variabeln name är samma som 'Micke'");
}
```

{% endcode %}

## else

Kompletterar en if-sats. Skrivs innan ett kodblock som ska köras om if-satsens kriterium inte stämmer.

{% code lineNumbers="true" %}

```csharp
if (i > 4)
{
  Console.WriteLine("Högre än fyra!");
}
else
{
  Console.WriteLine("Inte högre än fyra!");
}
```

{% endcode %}

## else if

Används för att skapa en kedja av if-satser, där varje if-sats bara kollas om den föregående inte satsens kriterium inte uppnåddes.

{% code lineNumbers="true" %}

```csharp
if (i > 4)
{
  Console.WriteLine("Högre än fyra!");
}
else if (i < 0)
{
  Console.WriteLine("Lägre än noll!");
}
else
{
  Console.WriteLine("Högre än noll, lägre än fem!");
}
```

{% endcode %}


# Switch-case

Switch-case kan användas som ett alternativ till [if-satser](/grundlaggande/if-satser).

```csharp
int choice = 1;

switch(choice)
{
  case 1:
    Console.WriteLine("So you choose 1!");
    break;
  case 2:
    Console.WriteLine("So you choose 2!");
    break;
  case 3:
    Console.WriteLine("So you choose 3!");
    break;
  default:
    Console.WriteLine("That is not a valid choice!");
    break;
}
```

Man skriver alltså `switch` och sedan inom parenteser ett uttryck (t.ex. en variabel) som ska jämföras med flera olika *cases*.

Sedan skriver man ett antal `case`, där varje case är ett möjligt värde som uttrycket kan vara. I exemplet finns case 1, 2 och 3. Observera att man skriver : efter varje case och avslutar med en `break`.

Slutligen kan man ha en `default`, som är ett special-case som man hamnar i om uttrycket inte matchar något av de case man skrivit. Det är frivilligt att ha en default.

Har man ingen break så fortsätter koden att köras; på så vis kan man ha en kod som körs vid flera olika cases:

```cpp
int answer = 1;
int pts = 0;

switch(answer)
{
  case 1:
  case 2:
    Console.WriteLine("Not the right answer!");
    break;
  case 3:
    Console.WriteLine("Correct!");
    pts++;
    break;
  default:
    Console.WriteLine("That is not a valid answer!");
    break;
}
```


# Loopar

## while-loop

Fungerar och ser ut som en [if-sats](/grundlaggande/if-satser) utom att körningen inte fortsätter när kodblocket körts, utan "hoppar upp" till kriteriet och testar det igen.

Precis som med if-satserna ska det som är mellan paranteserna vara kod som ger [boolskt](/grundlaggande/datatyper#bool) resultat t.ex. en [jämförelse ](/grundlaggande/operatorer#boolska)eller en metod som [returnerar ](/grundlaggande/metoder#returnering)ett boolskt värde.

While-loopar används när man **inte vet** hur många gånger loopen ska köras. Till exempel:

{% code lineNumbers="true" %}

```csharp
string name = "";

// Körs så många gånger som behövs för att 
// användaren ska förstå att hen ska skriva "Micke"
while (name != "Micke")
{
  Console.WriteLine("Skriv ditt namn:")
  name = Console.ReadLine();
}
```

{% endcode %}

## for-loop

Fungerar som en while-loop men har alltid en räknare – bra när man vill göra något ett visst antal gånger. Samlar deklaration av räknare, kriterie för att fortsätta loopa och förändring av räknarens värde på samma ställe.

{% code lineNumbers="true" %}

```csharp
// i är räknarvariabeln, vars värder börjar på 0
// i < 10 är villkoret; så länge det utvärderas som sant fortsätter loopen köras
// i++ körs i slutet av varje iteration, och betyder att i ökar med 1 varje gång

for (int i = 0; i < 10; i++)
{
  Console.WriteLine(i);
}
```

{% endcode %}

For-loopar används när man **vet** hur många gånger loopen ska köras – åtminstone när man når den. Så länge en räknare ska användas fungerar en for-loop bra.

## Nästlad for-loop

En teknik som ofta används för att göra till exempel rutnät eller andra 2d-grejer.

```csharp
for (int y = 0; y < 5; y++)
{
  for (int x = 0; x < 5; x++)
  {
    Console.Write ("o ");
  }
  Console.WriteLine();
}
```

Resultatet av koden blir:

```
o o o o o
o o o o o
o o o o o
o o o o o
o o o o o
```

## foreach-loop

Foreach-loopar är i princip likadana som for-loopar men är specialdesignade för att gå igenom listor och arrayer. En foreach-loop körs lika många gånger som det finns saker i en lista/array, och varje gång loopen körs så lagras en av sakerna i variabeln som anges.

Nackdelen jämfört med en for-loop är att man inte får ut vilket index (plats i listan/arrayen) respektive sak har. Behöver man skriva ut index eller använda det på något vis är därför for-loop ett bättre val.

{% code lineNumbers="true" %}

```csharp
string[] choices = {"Start", "Options", "Quit"};

foreach (string choice in choices)
{
  Console.WriteLine(choice);
}
```

{% endcode %}

## Break

Används för att hoppa ur en loop.

```csharp
while (true)
{
  string name = Console.ReadLine();
  if (name == "Kalle")
  {
    break; // Hoppar ur loopen helt om name är "kalle" 
  }
}
```

## Continue

Används för att hoppa till nästa iteration av loopen.

```csharp
for (int i = 0; i < 10; i++)
{
  if (i == 5)
  {
    continue; // Skippar resten av iterationen; skriver alltså inte ut 5
  }
  Console.WriteLine(i)
}
```


# Listor och arrayer

Både listor och arrayer är samlingar, som (förenklat) låter oss lagra flera värden av samma datatyp på samma ställe. Man kan till exempel ha en samling av en massa int-värden som är samlade på samma ställe, eller en samling strings.

* **Arrayer** kom först, är snabba och effektiva, men kan inte växa/krympa – de har ett fast antal platser.
* **Listor** är en senare uppfinning. De är mer flexibla och nästan lika snabba. De är en [generisk klass](/klasser-och-objektorientering/generiska-klasser#list) och de kan växa/krympa.

## Indexering

Alla föremål som lagrats i en samling ges normalt ett index, som beskriver föremålets position i samlingen och låter oss komma åt det.

I arrayer och listor är index alltid en siffra – en integer. Det första föremålet i listan har index 0, det andra har index 1, etc.

{% code lineNumbers="true" %}

```csharp
string[] names = ["Benny", "Jenny", "Kenny", "Anna"];
// I denna array har Benny index 0, Jenny 1, Kenny 2 och Anna 3.

Console.WriteLine(names[2]); // Skriver ut "Kenny"
```

{% endcode %}

För att hänvisa till ett index räknat från slutet av arrayen så skriver man ^ framför siffran.

{% code lineNumbers="true" %}

```csharp
string[] names = ["Benny", "Jenny", "Kenny", "Anna"];

Console.WriteLine(names[^2]); // Skriver ut "Jenny"
```

{% endcode %}

## List

När listor skapas har de normalt sett en längd på 0, och de **växer dynamiskt** när man lägger till saker i dem.

{% code lineNumbers="true" %}

```csharp
// Skapa en tom string-lista
List<string> listNamn = [];

// Skapa en string-lista som redan från början innehåller tre värden
List<string> choices = ["Start", "Options", "Quit"];
```

{% endcode %}

Mer information om List finns under [Generiska klasser](/klasser-och-objektorientering/generiska-klasser).

### Add()

Metod som är inbyggd i listor. Används för att lägga till nya föremål i listan.

```csharp
listNamn.Add("Kim");
```

### Count

Variabel som är inbyggd i listor. Har alltid ett värde som är lika med listans storlek.

{% code lineNumbers="true" %}

```csharp
// Skapa en integer-variabel och tilldela den värdet som motsvarar listans storlek
int length = listNamn.Count;
```

{% endcode %}

### Remove()

Metod som är inbyggd i listor. Används för att ta bort föremål från listan.

```csharp
listNamn.Remove("Kim");
```

### RemoveAt()

Metod som är inbyggd i listor. Används för att ta bort föremål på en specifik plats i listan.

```csharp
listNamn.RemoveAt(4);
```

### RemoveAll()

Metod för att ta bort alla föremål som matchar ett visst kriterium. Kriteriet skrivs som en metod. Metoden tar emot ett värde av samma datatyp som listan innehåller, och returnerar true om kriteriet är uppfyllt och false om det inte är det. Här används med andra ord [delegates](/grundlaggande/delegates).

{% code lineNumbers="true" %}

```csharp
// IsAboveScreen är kriteriet
static bool IsAboveScreen(Rectangle r)
{
  return r.y < 0;
}

static void Main(string[] args)
{
  List<Rectangle> rects = new List<Rectangle>();

  /* ... */

  // Tar bort alla rektanglar som, när de stoppas in 
  // i metoden, får den att returnera true
  rects.RemoveAll(IsAboveScreen);
```

{% endcode %}

Ett annat sätt är att använda ett [lambda-uttryck](/grundlaggande/delegates#lambdas):

```csharp
rects.removeAll(rect => rect.y < 0);
```

### Att göra om en lista till en array

```csharp
string[] aNamn = listNamn.ToArray();
```

### Att göra om en array till en lista

```csharp
List<string> listNamn = new List<string>(aNamn);
```

## Array

Arrayer har en **fast längd** som bestäms när arrayen skapas.

{% code lineNumbers="true" %}

```csharp
// Skapa en int-array med tre tomma platser
int[] arrayHp = new int[3];

// Skapa en string-array med tre platser som redan från början ges värden
string[] choices = ["Start", "Options", "Quit"];
```

{% endcode %}

### Length

Variabel som är inbyggd i arrayer. Har alltid ett värde som är lika med arrayens storlek.

{% code lineNumbers="true" %}

```csharp
// Skapa en integer-variabel och tilldela den värdet som motsvarar 
// arrayens storlek
int length = arrayHp.Length;
```

{% endcode %}

### Contains()

Ett snabbt sätt att se ifall en sak finns i arrayen.

```csharp
string choice = Console.ReadLine();
bool validAnswer = choices.Contains(choice);
```

{% hint style="warning" %}
**OBSERVERA:** Contains är en del av biblioteket Linq, så du behöver skriva detta längst upp bland dina andra using-statements:

**`using System.Linq;`**
{% endhint %}

### Range

För att få ut en del av en array som en ny array kan man använda *ranges*.

Ranges anger man genom att skriva `..` (två punkter). Innan punkten skriver man start-index, alltså den sak i arrayen man vill att den nya arrayen ska börja på. Efter punkterna skriver man slut-index. Den nya arrayen inkluderar inte den sak som finns på slut-index.

{% code lineNumbers="true" %}

```csharp
string[] names = ["Benny", "Jenny", "Kenny", "Anna", "Mahmud", "Ki"];

string[] subNames = names[1..3]; // subNames blir en array med Jenny och Kenny

string[] firstHalf = names[..3]; // blir Benny, Jenny och Kenny

string[] secondHalf = names[3..]; // blir Anna, Mahmud och Ki

string[] lastTwo = names[^2..]; // blir Jenny och Kenny
```

{% endcode %}

Detta kallas ibland också "slicing", eftersom man delar upp arrayen i mindre bitar.

### Att göra om en array till en lista

{% code lineNumbers="true" %}

```csharp
// Skapa en string-lista baserat på arrayHp, med samma innehåll och storlek
List<string> lNamn = new List<string>(arrayHp);
```

{% endcode %}

### Flerdimensionella arrayer

En vanlig array är **endimensionell** – en lista, eller en serie. Varje sak i arrayen identifieras av **ett** index.

En tvådimensionell array är som ett rutnät eller en tabell. Varje sak i arrayen identifieras av **två** index.

{% code lineNumbers="true" %}

```csharp
// Skapa en tvådimensionell array med 150 platser; 10 rader med 15 kolumner
int[,] grid = new int[10,15];

// Bestäm värdet på position 2,2 till 1
grid[2,2] = 1;
```

{% endcode %}

#### GetLength

För att läsa av en flerdimensionell arrays längd i någon dimension, använd GetLength.

{% code lineNumbers="true" %}

```csharp
for (int y = 0; y < grid.GetLength(1); y++)
{
  for (int x = 0; x < grid.GetLength(0); x++)
  {
    grid[x, y] = 0;
  }
}
```

{% endcode %}

## Skapa i äldre versioner (innan .net 8)

Innan C# 12, som ingår i dotnet 8, kunde man inte skapa nya arrayer eller listor via "collection expressions", alltså de enkla hakparenteserna.

Istället var man tvungen att använda måsvingar för arrayer, och new() för List.

```csharp
List<int> integerList = new() {1, 2, 3, 4};
int[] integerArray = {5, 6, 7, 8};
```


# Slump (Random)

## Slumpgenerator

En slumpgenerator är ett objekt som används för att generera slumptal.

{% code lineNumbers="true" %}

```csharp
// Skapar en slumpgenerator och gör så att vi kan komma åt den 
// med hjälp av variabeln "generator".
Random generator = new Random();
```

{% endcode %}

I Dotnet 6 och senare finns också en färdig slumpgenerator i `Random.Shared`.

## Next – heltal (int)

Används för att slumpa heltal (int).

{% code lineNumbers="true" %}

```csharp
// Slumpar ett heltal mellan 0 och det största heltal int kan innehålla
int r = Random.Shared.Next();
```

{% endcode %}

Next kan anropas med en [parameter ](/grundlaggande/metoder#parametrar)som anger "taket" för slumpen. Taket är exklusivt, dvs det tal som anges kommer aldrig att slumpas - bara lägre tal.

{% code lineNumbers="true" %}

```csharp
// Slumpar ett heltal som är 0, 1, 2 eller 3
int r = Random.Shared.Next(4);
```

{% endcode %}

Om man anger två parametrar så tolkas den första som ett golv, och den andra som ett tak. Golvet är inklusivt, dvs det tal som anges kan komma att slumpas fram.

{% code lineNumbers="true" %}

```csharp
// Slumpar ett heltal som är 2, 3 eller 4
int r = Random.Shared.Next(2,5);
```

{% endcode %}

## NextDouble – decimaltal

Används för att slumpa decimaltal mellan 0 och 1. Man får värdet i form av en double, så den behöver dels multipliceras med ett tal för att bli något annat än 0–1, och dels konverteras till float.

```csharp
float percent = (float) Random.Shared.NextDouble() * 100f;
```


# Metoder

## Enkel metod

En metod är ett namngivet kodblock, som kan anropas från andra delar av koden genom att man skriver dess namn. Det gör att koden kan återanvändas och man slipper skriva samma kod flera gånger.

{% code lineNumbers="true" %}

```csharp
static void MetodensNamn()
{
  Console.WriteLine("Hej!");
}
```

{% endcode %}

För att anropa metoden skriver man sedan:

```csharp
MetodensNamn();
```

"static"-delen behövs *enbart* om metoden ska kunna anropas från en annan metod som också är static, till exempel Main.

För mer information om vad "static" egentligen betyder – [läs här](/klasser-och-objektorientering/static).

## Parametrar

Genom parametrar kan man föra in information i metoden när den anropas.

{% code lineNumbers="true" %}

```csharp
static void PrettyPrint(string text)
{
  Console.WriteLine($"--~~== {text} ==~~--");
}
```

{% endcode %}

För att deklarera värdet av parametern vars namn är text anropas metoden ovan såhär:

```csharp
PrettyPrint("Horsies!");
```

Resultatet blir att följande skrivs ut till konsolen:

```
--~~== Horsies! ==~~--
```

## Returnering

För att få ut information ur en metod så att informationen kan användas i resten av programmet används returnering. Det innebär att man istället för void skriver vilken datatyp informationen man vill få ut från metoden ska ha, och sedan någonstans i metoden skriver return följt av en information som har denna datatyp.

{% code lineNumbers="true" %}

```csharp
static float OneThird()
{
  float result = 1f / 3f;
  return result;
} 
```

{% endcode %}

När man sedan anropar metoden så fångar man upp den returnerade informationen i en variabel.

```csharp
float f = OneThird();
```

Ofta kombinerar man parametrar och returneringar för att bygga metoder som bearbetar den information man stoppar in på något sätt.

{% code lineNumbers="true" %}

```csharp
static int Multiply(int a, int b)
{
  int result = a * b;
  return result;
}
```

{% endcode %}

Och ovanstående metod anropas såhär:

```csharp
int area = Multiply(3, 4);
```

Resultatet blir att 3 multipliceras med 4 inuti metoden, och resultatet (12) returneras och lagras i variabeln `area`.

## Överlagring

Att överlagra metoder innebär att man döper flera metoder till samma namn, men låter dem ha olika parametrar. **Detta kan bara göras med klassmetoder**, alltså inte med metoder som skrivs direkt i program.cs.

Effekten blir att när man anropar metodnamnet så används de parametervärden man anger för att avgöra vilken av de olika metoderna som ska köras.

{% code lineNumbers="true" %}

```csharp
static void Shout() // Version 1, utan parametrar
{
  Console.WriteLine("AAAAAAAAH!");
}
```

{% endcode %}

{% code lineNumbers="true" %}

```csharp
static void Shout(string exclamation) // Version 2, med en parameter
{
  Console.WriteLine(exclamation.ToUpper());
}
```

{% endcode %}

De två Shout-metoderna ovan har samma namn, men den ena tar emot en parameter.

```csharp
Shout(); // Version 1 anropas
Shout("abracadabra!"); // Version 2 anropas
```

När de anropas, väljer C# *den version som bäst matchar anropet*.

## Generiska metoder

Generiska metoder är metoder där datatypen för någon eller några av variablerna eller parametrarna inte bestäms när metoden deklareras, utan när den anropas.

I exemplet nedan används 1 typ-parameter, "T". Efter att den skrivits mellan <> efter metodens namn så kan T användas i koden som om den vore en datatyp.

{% code lineNumbers="true" %}

```csharp
static void PrintInRed<T>(T content)
{
  ConsoleColor defaultColor = Console.ForegroundColor;
  Console.ForegroundColor = ConsoleColor.Red;
  Console.WriteLine(content);
  Console.ForegroundColor = defaultColor;
}
```

{% endcode %}

När metoden sedan anropas så anges vilken datatyp T ska vara vid just det anropet genom att datatypen skrivs mellan <> efter metodens namn.

{% code lineNumbers="true" %}

```csharp
PrintInRed<int>(8);
PrintInRed<string>("Hello, World!");
```

{% endcode %}

Detta liknar hur [generiska klasser](/klasser-och-objektorientering/generiska-klasser) fungerar.


# Använda bibliotek (using)

C# har ett antal inbyggda kodbibliotek. Man kan lägga till ytterligare bibliotek i ett specifikt projekt genom NuGet-paket.

## Using

Skrivs högst upp i en cs-fil för att deklarera att innehållet i ett visst bibliotek ska användas.

{% code lineNumbers="true" %}

```csharp
using System;
using System.Net;
using System.Collections.Generic;
using System.Text.Json;
```

{% endcode %}

Man kan alltid använda sig av bibliotekens innehåll utan att skriva using, men då måste man skriva hela bibliotekets namn varje gång.

{% code lineNumbers="true" %}

```csharp
// Utan "using System":
System.Console.WriteLine("Hello");

// Med "using System":
Console.WriteLine("Hello");

// Utan "using System.Collections.Generic":
System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>();

// Med "using System.Collections.Generic":
List<string> list = new List<string>();
```

{% endcode %}

### Global using (.NET 6)

I .NET 6 introduceras globala using-statements. De måste skrivas ovanför alla vanliga using-statements.

```csharp
global using System.IO;
```

De gör att man bara behöver skriva varje using-statement en gång per projekt. Lämpligtvis samlar man dem då i samma fil.

### Implicit using (.NET 6)

I .NET 6 ingår som standard vissa globala using-statements utan att man behöver skriva dem. I konsollprogram ingår:

{% code lineNumbers="true" %}

```csharp
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
```

{% endcode %}

## NuGet Gallery

NuGet Gallery är ett Visual Studio Code-tillägg som gör att man kan söka efter och lägga till nya bibliotek till sitt projekt. De är packeterade som NuGet-paket, och Gallery hjälper till att hitta, laddaner och installera dem.

Man kommer åt tillägget genom att trycka F1 och söka efter det.

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FSvd98uLK5vGov6h5x0Py%2Fimage.png?alt=media\&token=dbedb499-0649-4971-aef1-9718caf19465)

Därefter söker man efter det bibliotek man vill ha, till exempel Raylib eller Restsharp. Man markerar biblioteket man vill ha, sedan kan man trycka på "Install"-länken som står bredvid ens projekts csproj-fil i högerspalten.

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2Ff1IxEnNYxsSbMZljxOAI%2Fimage.png?alt=media\&token=163a908b-8cdb-4338-9ff9-05ec72bec84d)

## NuGet via terminalen

Om man känner till NuGet-paketets namn så kan man använda terminalkommandon istället. Man placerar sig då först i mappen där projektets csproj-fil ligger och sedan skriver man till exempel:

```powershell
dotnet add package Raylib-cs
```

Då kommer dotnet att upptäcka csproj-filen, lägga in en referens till biblioteket i den, och sedan se till att NuGet-paketet laddas ner och packas upp.


# Delegates, events och lambdas

{% hint style="info" %}
**OBS:** Lite överkurs =)
{% endhint %}

Delegates är ett sätt att kunna göra så att variabler pekar mot metoder istället för mot värden eller objekt i minnet. De är lite överkurs, men ganska användbara.

{% code lineNumbers="true" %}

```csharp
// Skapar en delegate som passar in på metoder som 
// inte tar emot några parametrar eller returnerar något.
delegate void Task(); 

// En metod som passar in på delegaten
static void SayHello() {
  System.WriteLine("Hello!");
}

static void Main(string[] args)
{
  Task t = SayHello; // Lagra en referens till SayHello-metoden i "t"
  t(); // Att köra t som en metod är nu samma sak som att köra SayHello.
}
```

{% endcode %}

När man skapar en delegat så beskriver den en metodprofil. Man kan säga att varje delegat beskriver en **kategori** av metoder.

{% code lineNumbers="true" %}

```csharp
// Stämmer in på metoder som tar emot en int-parameter och inte returnerar något.
delegate void DelegateOne(int y);

// Stämmer in på metoder som returnerar en int utan att ta emot några parametrar.
delegate int DelegateTwo();

// Stämmer in på metoder som returnerar en float efter att ha tagit emot
// en string och en int.
delegate float DelegateThree(string x, int y);
```

{% endcode %}

När man skapat sin delegat används den alltså som om den vore en datatyp. När man lagrar metoderna i den så ser man till att inte använda () efter metodnamnet, för då körs ju metoden istället, innan tilldelningen.

```csharp
DelegateOne test = MethodOne;
```

## Action <a href="#action" id="action"></a>

En Action är en generisk delegat som passar in på metoder som inte returnerar ett värde. Om man vill matcha metoder som tar emot parametrar kan dessa anges mellan <>.

{% code lineNumbers="true" %}

```
static void Hello()
{
  Console.WriteLine("Hello");
}

static void HelloTo(string target)
{
  Console.WriteLine($"Hello {target}");
}

Action example1 = Hello;
Action<string> example2 = HelloTo

example1();
example2("Micke");
```

{% endcode %}

### Dictionary med Actions <a href="#h.p_qt3arehin8yt" id="h.p_qt3arehin8yt"></a>

Ett exempel på hur man kan använda delegater.

{% code lineNumbers="true" %}

```csharp
Dictionary<string, Action> actions = new Dictionary<string, Action>();

actions.Add("first", DoFirst);
actions.Add("second", DoSecond);
  
actions["first"](); // Kör DoFirst-metoden


static void DoFirst()
{
  /* .. */
}

static void DoSecond()
{
  /* .. */
}
```

{% endcode %}

## Func

Func är en generisk delegat som matchar metoder som returnerar något. En eller flera datatyper anges inom <>. Anges flera så är den sista alltid returtypen, resten är parametrar.

```csharp
static int Addition(int a, int b)
{
  return a + b;
}

static string MakeStrengthString(int str)
{
  return $"Strength: {str}";
}

Func<int, int, int> math = Addition;

Func<int, string> statDisplay = MakeStrengthString;

int y = math(3,4);

string strength = statDisplay(14);
```

## Anonyma metoder i delegatvariabler

Anonyma metoder saknar eget namn.

{% code lineNumbers="true" %}

```csharp
static void Main(string[] args)
{
  Action t = delegate()
    {
      System.WriteLine("Hello!");
    }
    
  t();
}
```

{% endcode %}

De är praktiska när man aldrig faktiskt kommer att anropa metoden med dess eget namn, utan bara vill kunna lägga in den i en variabel eller en lista.

{% code lineNumbers="true" %}

```csharp
Dictionary<string, Action> actions = new Dictionary<string, Action>();

actions.Add("greet", 
  delegate ()
  {
    Console.WriteLine("Hello");
  }
);

actions["greet"]();
```

{% endcode %}

## Multicasting: delegat-variabler med flera metoder

Om man vill att flera metoder ska köras när en delegat-variabel anropas så kan man kombinera delegater för att skapa s.k. [multicast-delegater](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/how-to-combine-delegates-multicast-delegates).

{% code lineNumbers="true" %}

```csharp
Action multiCaster = delegate() { Console.WriteLine("Hello"); };

multiCaster += delegate() { Console.WriteLine("World"); };

multiCaster(); // Skriver först ut Hello, sedan World
```

{% endcode %}

{% code lineNumbers="true" %}

```csharp
Action good = delegate() { Console.WriteLine("Good"); };

Action bye = delegate() { Console.WriteLine("Bye"); };

Action morning = delegate() { Console.WriteLine("Morning"); };

Action goodMorning = good + morning;
Action goodBye = good + bye;

goodMorning(); // Skriver ut "Good" och "Morning"
goodBye(); // Skriver ut "Good" och "Bye"
```

{% endcode %}

Att lägga till en metod till en multicast-delegat kallas **subscribing**, och att ta bort en metod från en multicast-delegat kallas **unsubscribing**.

## Events

Nackdelen med multicast-delegater är att den som har tillgång till dem inte bara kan lägga till nya metoder i dem, utan också aktivera dem och göra större ändringar – som att till exempel ändra dem till null.

Med en event kan den som har tillgång utifrån **bara** lägga till och ta bort metoder (subscribe/unsubscribe)

{% hint style="info" %}
**Events kan bara existera i klasser**, och de kan bara anropas (invoke) inifrån den klassen
{% endhint %}

{% code title="Avatar.cs" lineNumbers="true" %}

```csharp
public class Avatar
{
  public event Action OnDeath; // OBS: nyckelordet "event"

  public Avatar()
  {
    OnDeath += DeathMessage; // Subscribe:a klassmetoden DeathMessage
  }

  public void Update()
  {
    OnDeath.Invoke(); // Aktivera (invoke) eventet
  }

  public void DeathMessage() { Console.WriteLine("YOU DIED"); }
}
```

{% endcode %}

{% code title="Program.cs" lineNumbers="true" %}

```csharp
Avatar p = new Avatar();

Action PauseGame = delegate() { Console.WriteLine("Game is paused"); };

// Subscribe:a den lokala metoden PauseGame till eventet OnDeath
p.OnDeath += PauseGame;

p.Update(); // Kör Update-metoden, som i sin tur invoke:ar eventet
```

{% endcode %}

## Lambdas

Lambda-uttryck är, enkelt uttryckt, ett sätt att skriva väldigt enkla anonyma metoder (anonyma delegater) vars returvärden är direkta resultat av deras parametrar. Ett lambda-uttryck består av en parentes där den anonyma metodens parametervärden anges, en => och slutligen en enkel uträkning som motsvarar det som ska returneras från metoden.

Uträkningen kan bytas ut mot ett kodblock som returnerar ett värde, om mer omfattande

{% code lineNumbers="true" %}

```csharp
// Delegat som passar alla metoder som tar emot två int-parametrar och
// som returnerar en int som resultat
delegate int Calculation(int x, int y);

static void Main(string[] args)
{
  // Lambda-uttrycket => har två inputs på vänster sida, 
  // och uträkningen på höger sida resulterar i en int.
  // Därför passar lambda-uttrycket in på delegaten Calculation.
  Calculation c = (xInput, xOutput) => xInput * xOutput;

  int result = c(10, 5);
  
  // Detta gör samma sak som ovan, men med ett kodblock istället 
  // för en ren beräkning
  Calculation c2 = (xInput, xOutput) => {return xInput * xOutput};
}
```

{% endcode %}

Lambdas används väldigt ofta när man till exempel vill filtrera en lista på något sätt.

{% code lineNumbers="true" %}

```csharp
List<int> numbers = new List<int>() {2,3,4,5,6};

// FindAll returnerar en lista med alla föremål i listan som matchar ett visst
// kriterium. Kriteriet ska vara utformat som en metod, som tar emot ett
// föremål av rätt datatyp som parameter och returnerar en bool.
// lambda-uttrycket nedan tar emot en input på vänster sida (n) och uttrycket
// på höger sida är en boolsk jämförelse.
// Därför kommer lowNumbers att innehålla en lista med alla integers från
// numbers, som är < 4.
List<int> lowNumbers = numbers.FindAll(n => n < 4);
```

{% endcode %}

De kan också användas till events och till multicast-delegates. Ofta används detta när det bara är ganska lite kod som ska köras.

{% code lineNumbers="true" %}

```csharp
Avatar p = new Avatar();

p.OnDeath += () => Console.WriteLine("Game is paused");
```

{% endcode %}


# Matematik (Math)

## Math.Abs()

Returnerar det absoluta värdet hos ett tal som anges som parameter.

```csharp
float y = Math.Abs(-0.45f); // y får värdet 0.45
```

## Math.Sin(), Math.Cos(), Math.Tan()

Returnerar sinus, cosinus eller tangens av vinkeln som anges som parameter. Vinkeln behöver anges i radianer.

```csharp
float s = Math.Sin(3.4f);
```

De inverterade trigonomiska funktionerna finns också - de heter Math.Asin, Math.Acos och Math.Atan.

## Math.Max()

Returnerar det största av två värden som anges som parametrar

```csharp
int i = Math.Max(4, 12); // i blir 12.
```

## Math.Min()

Returnerar det minsta av två värden som anges som parametrar

```csharp
int i = Math.Min(4, 12); // i blir 4.
```


# Vektorer (Numerics)

Numerics är ett bibliotek som innehåller mer avancerade numeriska typer, som komplement till de vanliga, t.ex. int.

```csharp
using System.Numerics;
```

De används ofta i spel, till exempel sådana man skapar med [Raylib](/annat/raylib). Däremot har Unity sina egna Vector-klasser.

## Vector2

En Vector2 är en tvådimensionell vektor som består av två komposanter, en i x-led och en i y-led. Komposanterna har datatypen float.

{% code lineNumbers="true" %}

```csharp
// Skapa en vektor med X-värde 20 och Y-värde 30.5
Vector2 position = new Vector2(20f, 30.5f);
```

{% endcode %}

Man kan använda räknesätt med vektorer.

{% code lineNumbers="true" %}

```csharp
Vector2 position = new Vector2(20, 20);
Vector2 movement = new Vector2(0.1f, 0.1f);

// Adderar movement-vektorn till position-vektorn
position += movement;
```

{% endcode %}

Man kan till och med kombinera vektorer med vanliga siffror och räknesätt.

{% code lineNumbers="true" %}

```csharp
Vector2 position = new Vector2(20, 20);

// Skapar en vektor med X-värde 1 och Y-värde 0; 
// multiplicerar sedan både X och Y med 0.5.
Vector2 movement = new Vector2(1f, 0f) * 0.5f;

position += movement;
```

{% endcode %}

### X och Y

X och Y är float-egenskaper hos varje vektor.

{% code lineNumbers="true" %}

```csharp
Vector2 position = new Vector2(20, 30);

Console.WriteLine(position.X); // 20
Console.WriteLine(position.Y); // 30
```

{% endcode %}

### Length()

En metod inbyggd i varje vektor. Ger vektorns storlek (magnitud) som en [float](/grundlaggande/datatyper#float).

{% code lineNumbers="true" %}

```csharp
Vector2 position = new Vector2(20, 20);
float l = position.Length(); // 28.284271
```

{% endcode %}

### Vector2.Distance()

Ger avståndet mellan två vektorer som en float.

{% code lineNumbers="true" %}

```csharp
Vector2 position = new Vector2(20, 20);
Vector2 enemyPosition = new Vector2(30, 30);

float d = Vector2.Distance(position, enemyPosition); // 14.142136
```

{% endcode %}

### Vector2.Normalize()

Ger en normaliserad version av en vektor.

{% code lineNumbers="true" %}

```csharp
Vector2 position = new Vector2(20, 10);

// Ger en vektor med storlek 1, X 0.8944272 och Y 0.4472136
Vector2 n = Vector2.Normalize(position);
```

{% endcode %}


# Datum och tid

(Under uppbyggnad)

## DateTime

Datatyp – mer exakt en [klass ](/klasser-och-objektorientering/klasser-och-instanser)– som lagrar tidpunkter.

{% code lineNumbers="true" %}

```csharp
// Datumet 10:e december 1815
DateTime lovelaceBirthday = new DateTime(1815, 12, 10);

// Tidpunkten 14:32:00 på datumet 1969-07-16
DateTime apolloEleven = new DateTime(1969, 8, 16, 14, 32, 0);
```

{% endcode %}

### Egenskaper

Man kan få ut information ur DateTime-objekt genom att läsa av dess egenskaper. (Alla dessa är i själva verket [properties](/klasser-och-objektorientering/inkapsling-och-properties#properties).)

{% code lineNumbers="true" %}

```csharp
lovelaceBirthday.DayOfWeek; // vilken dag i veckan det är
lovelaceBirthday.Year;
lovelaceBirthday.Month;
lovelaceBirthday.Day; // Dag i månaden
apolloEleven.Hour; // 14
apolloEleven.Minute; // 32
apolloEleven.Second; // 0
apolloEleven.Millisecond; // 0
```

{% endcode %}

### Metoder

Man kan justera ett DateTime-objekts innehåll genom att anropa dess metoder.

{% code lineNumbers="true" %}

```csharp
// Flytta fram klockan
apolloEleven.AddYears(1);
apolloEleven.AddMonths(2);
apolloEleven.AddDays(14);
apolloEleven.AddHours(2);
apolloEleven.AddMinutes(30);
apolloEleven.AddSeconds(10);
apolloEleven.AddMilliseconds(300);
```

{% endcode %}

Alla dessa kan också användas för att flytta klockan bakåt – då stoppar man helt enkelt in negativa tal.

## DateTime.Now

Tidpunkten *just nu*. (Är egentligen en [static ](/klasser-och-objektorientering/static#statiska-variabler)[property](/klasser-och-objektorientering/inkapsling-och-properties#properties))

{% code lineNumbers="true" %}

```csharp
// Spara en kopia av tidpunkten "just nu" i variabeln startTime
DateTime startTime = DateTime.Now;
```

{% endcode %}

## TimeSpan

Datatyp som beskriver ett tidsspann, till exempel "tiden mellan 26:e mars 1926 och 27:e februari 2015".

Om man subtraherar en DateTime från en annan DateTime så blir resultatet en TimeSpan.

{% code lineNumbers="true" %}

```csharp
DateTime leonardBirth = new DateTime(1926, 3, 26);
DateTime leonardDeath = new DateTime(2015, 2, 27);

TimeSpan life = leonardDeath - leonardBirth;
```

{% endcode %}

### Tidsenheter i en TimeSpan

{% code lineNumbers="true" %}

```csharp
// Dagar
Console.WriteLine(life.Days); // en int: 32480 hela dagar i spannet
Console.WriteLine(life.TotalDays); // en double, som inkluderar delar av dagar

// Timmar
Console.WriteLine(life.Hours); // Timme-komponenten för spannet. Går mellan -23 och 23.
Console.WriteLine(life.TotalHours); // En double: 779520 hela timmar i spannet

// Minuter
Console.WriteLine(life.Minutes); // Minut-komponenten för spannet. Går mellan -59 och 59.
Console.WriteLine(life.TotalMinutes); // En double: 46771200 minuter i spannet

// Sekunder
Console.WriteLine(life.Seconds); // Timme-komponenten för spannet. Går mellan -59 och 59.
Console.WriteLine(life.TotalSeconds); // En double: 2806272000 sekunder i spannet

// Millisekunder
Console.WriteLine(life.Milliseconds); // Timme-komponenten för spannet. Går mellan -59 och 59.
Console.WriteLine(life.TotalMilliseconds); // En double: 2806272000000 millisekunder i spannet
```

{% endcode %}

## Att mäta tid

Ett vanligt användningsområde för DateTime och TimeSpan är att mäta hur lång tid något tar.

{% code lineNumbers="true" %}

```csharp
DateTime start = DateTime.Now

// Någon tung och jobbig kod körs här

DateTime end = DateTime.Now

TimeSpan span = end - start;

Console.WriteLine("Det tog:");
Console.WriteLine($"{span.Hours} timmar");
Console.WriteLine($"{span.Minutes} minuter");
Console.WriteLine($"{span.Seconds} sekunder");
Console.WriteLine($"{span.Milliseconds} millisekunder");
```

{% endcode %}


# Try-catch och Exception

## Try och catch

När man lägger in kod i ett try-block så förhindrar det att programmet avslutas när ett runtime-fel inträffar, t.ex. att man försöker konvertera något som inte kan konverteras eller komma åt ett index som inte finns i en array. Kort sagt *försöker* C# köra koden. Istället avbryts körningen, och programmet hoppar istället ner till det catch-block som står under.

{% code lineNumbers="true" %}

```csharp
int[] nums = {4, 5, 7};

try
{
  Console.WriteLine(nums[8]); // Orsakar ett IndexOutOfRange-fel
}
catch
{
  Console.WriteLine("Nope!");
}
```

{% endcode %}

Ett Try-block måste alltid paras ihop med minst ett Catch-block.

## Att fånga specifika fel

När man får ett runtime-fel så talar C# alltid om vad det är för fel.

Om du vill skriva ett catch-block för att fånga ett specifikt fel så specificerar du feltypen inom parenteser.

{% code lineNumbers="true" %}

```csharp
int[] nums = { 4, 5, 7 };

try
{
  Console.WriteLine(nums[8]);
}
catch (System.IndexOutOfRangeException)
{
  Console.WriteLine("Fel index!");
}
```

{% endcode %}

Du kan skriva in flera olika catch-block om du vill:

{% code lineNumbers="true" %}

```csharp
int[] nums = { 4, 5, 7 };

try
{
  Console.WriteLine(nums[8]);
}
catch (System.IndexOutOfRangeException)
{
  Console.WriteLine("Fel index!");
}
catch
{
  Console.WriteLine("Något annat fel!");
}
```

{% endcode %}

## Throw

Om du vill kan du, i dina egna metoder, ge upphov till ett exception som sedan måste catch:as där metoden anropas. På så vis måste du inte hantera alla fel direkt, utan kan sköta allt sådant på ett ställe.

{% code lineNumbers="true" %}

```csharp
static int DoThing(int i)
{
  int[] nums = { 4, 5, 7 };
  
  if (i >= nums.Length || i < 0)
  {
    throw new IndexOutOfRangeException();
  }
  
  return nums[i];
}
```

{% endcode %}

### Kasta upp

Om du catch:ar ett fel du inte vill hantera direkt, så kan du helt enkelt använda **throw** för att tvinga den som anropade den nuvarande metoden att hantera felet.

{% code lineNumbers="true" %}

```csharp
static int DoThing(int i)
{
  int[] nums = { 4, 5, 7 };
  try
  {
    return nums[i];
  }
  catch
  {
    throw;
  }
}
```

{% endcode %}

### Exception-typer är klasser <a href="#h.p_-hpgx_vm4ynb" id="h.p_-hpgx_vm4ynb"></a>

`System.IndexOutOfRangeException` är en [klass](/klasser-och-objektorientering/klasser-och-instanser), liksom alla andra sorters exceptions. De har alla System.Exception som [basklass](/klasser-och-objektorientering/arv). Det gör att man kan fånga in alla exceptions genom att catch:a System.Exception och sedan undersöka felet man fått genom t.ex. `is`.

{% code lineNumbers="true" %}

```csharp
int[] nums = { 4, 5, 7 };
try
{
  Console.WriteLine(nums[8]);
}
catch (Exception e)
{
  if (e is System.IndexOutOfRangeException)
  {
    Console.WriteLine("Indexfel!");
  }
}
```

{% endcode %}


# Namngivning

## Språk och "bra namn"

Namnen i ett projekt bör alla vara **på samma språk** och följa samma mönster.

Ett bra namn är tydligt och beskriver informationen variabeln innehåller, eller den handling metoden gör. "hitPoints" är ett bättre namn än "x".

| Kategori                                                                                        | Grundtanke                                          | Bra exempelnamn                                                                |
| ----------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------ |
| <p><strong>Variabler</strong><br><strong>Parametrar</strong><br><strong>Properties</strong></p> | Den data som lagras                                 | <p>\_hitPoints<br>movementX<br>hasBeenHit<br>weaponDamage<br>moneyOwed</p>     |
| **Metoder**                                                                                     | <p>Den handling som utförs<br>Ett <em>verb</em></p> | <p>CheckCollision<br>Draw<br>Update<br>LoadSavegame<br>ApplyMovementVector</p> |
| **Klasser**                                                                                     | Kategorinamn i singular                             | <p>Enemy<br>Level<br>Powerup<br>Button<br>Book</p>                             |

## PascalCase och camelCase

* **PascalCase:** Inga mellanslag mellan orden, stor bokstav (versal) i början av varje ord.
* **camelCase:** Inga mellanslag mellan orden, liten bokstav i början men i övrigt stor bokstav (versal) i början av varje ord.

### Exempel

| Typ                                                                                | Modell     | Exempel                                                          |
| ---------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------- |
| **Projekt**                                                                        | PascalCase | <p>SpaceShooter</p><p>PacMan</p><p>BreakoutClone</p>             |
| [**Metoder**](/grundlaggande/metoder)                                              | PascalCase | <p>TakeDamage()</p><p>RestoreOriginalPosition()</p><p>Rest()</p> |
| [**Klasser**](/klasser-och-objektorientering/klasser-och-instanser)                | PascalCase | <p>Enemy</p><p>ProjectileTarget</p><p>PowerupBox</p>             |
| [**Properties**](/klasser-och-objektorientering/inkapsling-och-properties)         | PascalCase | HitPoints                                                        |
| <p><strong>Klassvariabler:</strong><br><strong>public, protected</strong></p>      | PascalCase | IsAlive                                                          |
| **Klassvariabler: private**                                                        | camelCase  | \_hitPoints                                                      |
| <p><strong>Lokala variabler</strong><br><strong>("vanliga variabler")</strong></p> | camelCase  | <p>hitPoints</p><p>mana</p><p>isFloating</p>                     |
| **Parametrar**                                                                     | camelCase  | <p>name</p><p>movementVector</p>                                 |

## Understreck

Understreck används i början av [privata/protected](/klasser-och-objektorientering/public-private-och-protected) variabler i [klasser](/klasser-och-objektorientering/klasser-och-instanser), och *ingen annanstans.*

```csharp
public class Fighter
{
  private int _hp;
  protected int _mana;
  public int ShoeSize;
  public int Level { get; protected set; }
}
```


# Begrepp

## Grundläggande

### Datatyp

En sorts information, till exempel heltal, decimaltal, text, datum, vektor.

### Variabel

En "behållare" som kan tilldelas ett innehåll i form av ett värde. Variabler har alltid en datatyp.

### Sekvens

Kod som körs uppifrån och ner.

### Selektion

En del av koden där körningen kan "hoppa ner" beroende på något villkor, t.ex. genom en if-sats.

### Iteration

En del av koden där körningen kan "hoppa upp" beroende på något villkor, t.ex. genom en while-loop

### Kodblock

Ett stycke kod som avgränsas från resten av programmet genom en { innan blocket och en } efter blocket.

### Metod

Ett namngivet kodblock, lite som ett separat program som kan köras av andra delar av koden.

### Returnering

Att föra ut data ur en metod så att datan kan användas i koden som anropade metoden.

### Parameter

Variabel-liknande, används för att föra in data i metoder.

### Array

En datatyp som innehåller flera av något, t.ex. flera tal, eller flera texter.

### Scope

Det sammanhang som en variabel eller en metod existerar inom; generellt existerar de bara inom det kodblock där de skapats.

## Objektorientering

### Klass

En ritning för hur en kategori av objekt ska se ut – vilka variabler och metoder de ska innehålla. Exempel: Fiender ska ha hp och kunna förflytta sig.

### Instans

Ett objekt som skapats baserat på en klass. Exempel: en specifik fiende på skärmen.

### Arv

Att man kan låta klasser bygga på varandra. Exempel: en Goomba är en sorts Enemy. Goomba-klassen får alla variabler och metoder som Enemy-klassen har.

### Basklass

En klass som en eller flera andra klasser ärver från.

### Subklass / child class

En klass som ärver från en annan klass.

### Konstruktor

En metod som automatiskt anropas när det skapas en instans av klassen konstruktorn tillhör.

### Inkapsling

Att man "kapslar in" variabler som ingår i en klass, så att de inte kan ändras utifrån direkt – t.ex. att man har en hp-variabel som bara kan ändras genom att man anropas klassens Hurt-metod och bara kan läsas av genom att anropa en GetHP-metod. Detta gör att den som designar klassen kan förhindra att variabeln ges felaktiga värden.

### Polymorfism

Närhelst en instans av en basklass ska lagras, t.ex. i en variabel, så kan man istället ange en instans av en subklass till den basklassen. Exempel: en variabel som har datatypen Enemy kan användas för att lagra instanser av Enemy eller av Goomba, om Goomba är en subklass till Enemy.

## Filhantering

### Fil

En avgränsad bit information på hårddisken som fått ett namn och som ligger i en mapp.

Filnamnet slutar nästan alltid med en punkt och sedan några tecken till, detta är "filändelsen" som Windows och andra operativsystem använder för att bestämma vilket program som ska öppnas när man dubbelklickar på den.

### Mapp

En "behållare" i ett filsystem som kan innehålla filer eller andra mappar.

### Serialisering

Att omvandla ett objekt – ofta en instans av en klass – eller flera till ett strukturerat textformat, t.ex. XML eller JSON.

### Deserialisering

Att omvandla strukturerad text (t.ex. XML eller JSON) som beskriver ett eller flera objekt till en instans av en klass.

## Nätverk

### Klient

Ett program som kontaktar en server för att få tillgång till någon form av tjänst eller information. Används ibland också om datorer som har sådana program installerade.

> **Exempel:** Chrome.

### Server

Ett program som tillhandahåller någon form av tjänst åt klienter. Används ibland också om datorer som har sådana program installerade och som mest finns till för att just tillhandahålla tjänster (och inte t.ex. spelas på).

> **Exempel:** Apache web server

### IP-adress

Address som identifierar en dator på ett nätverk. Ännu är IPv4 vanligast; exempel på IP-adress enligt IPv4 är 192.168.0.1. Fyra siffror 0–255 med punkter mellan. IPv6 har större tal och skriv som fyra grupper av hexadecimala tal t.ex. 2001:db8::8a2e:370:7334.

Vi använder IP-adresser för att bestämma vilken dator vi ska försöka koppla upp oss mot.

### API

Application Programming Interface. Hur program pratar med varandra. Man kan t.ex. säga att PokeApi har ett RESTful API som låter användare hämta information om Pokemons

### REST

REpresentational State Transfer. Beskriver en standard för kommunikation mellan en klient och en server; i vårt fall för att beskriva hur man utför CRUD-operationer på en server med hjälp av HTTP-standarden. Ett API som följer REST-standarden kallas för ett RESTful API.

### CRUD

Create, Read, Update och Delete. De fyra saker man vanligtvis behöver kunna göra med innehållet i en databas eller annan lagring.


# Reference vs value types

{% hint style="info" %}
**OBS:** Lite överkurs =)
{% endhint %}

## Identifiers

Variabelnamn är egentligen bara namn på specifika minnesplatser i datorns RAM-minne.

{% code lineNumbers="true" %}

```csharp
int t; // Reservera 32 bitar i datorns minne för att lagra heltal, 
       //  och namge den minnesadressen "t"
t = 8; // Lagra heltalet 8 i den minnesaddress som har namnet "t".
```

{% endcode %}

Namnet något får kallas för en **identifier**.

## Minnet – stacken och heapen

Förenklat delas datorns minne upp i två delar: **Stacken** och **heapen**.

**Stacken** är strukturerad, snabb och begränsad i storlek. Det man lägger i den finns bara kvar så länge det nuvarande kodblocket körs.

**Heapen** är ostrukturerad, stor och det man lägger i den lever kvar tills det tas bort. I en del språk betyder det att man alltid måste komma ihåg att ta bort saker som ligger där manuellt – i C# och en del andra språk finns s.k. Garbage Collection som då och då rensar bort saker i heapen som det inte längre finns någon identifier som pekar mot.

**Identifiers finns alltid i stacken.** I stacken skapas en koppling mellan identifiern och vad den är satt att identifiera. Så till exempel skapas här en koppling mellan identifiern "x" och värdet "10".

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2Fva8076UclauCnwKq5ReY%2FStack-Heap-x10.png?alt=media&amp;token=4289d8d3-b091-4ea3-b495-cb77d4694401" alt=""><figcaption></figcaption></figure>

## Value types

För datatyper som är **value types** lagras också **värdet** i stacken. Int är ett exempel på value type. Så när int-variabeln t skapas så är det i stacken namnet "t" associeras med ett 32-bitar stort minnesutrymme.

Exempel på value types:

* int, float och övriga numeriska typer.
* bool
* struct-typer

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2F64WoAOUQeYS1wCpL0VFF%2FStack-values.png?alt=media&amp;token=a3f8af92-95ee-4e9b-a4f3-460e8ee75efd" alt=""><figcaption></figcaption></figure>

## Reference types

För datatyper som är reference types lagras själva objektet, datan, i heapen. Det enda som lagras på minnesadressen i stacken är en **referens** vidare till platsen i stacken där datan finns.

Så identifiern pekar på en plats i stacken, på den platsen finns en vidarepekning till en plats i heapen.

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FjaRi87frhdRBn0LEAYpc%2FStack-Heap-References.png?alt=media&amp;token=3950f15b-3093-47d6-8fdb-785aa24bc73f" alt=""><figcaption><p>I stacken är axe-identifiern inte kopplad direkt till en instans av Weapon, utan till en minnesadress där det finns en sån instans.</p></figcaption></figure>

## Varför är det här viktigt?

### Tilldelning

Value types och reference types beter sig olika när tilldelnings-operatorn = används. Mer exakt beter de sig exakt lika – men eftersom de lagrar olika saker i stacken så blir effekten olika.

{% code lineNumbers="true" %}

```csharp
int a = 9;
int b = a; // Kopierar stack-positionen som identifiern a pekar på
           //  till stack-positionen som identifiern b pekar på.
```

{% endcode %}

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FAmyRiHyOcFrDCgbVcOAW%2FStack-values-before-copy.png?alt=media&amp;token=c1de6058-938a-439f-bb19-cd59d1f6d075" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FsUFEAmGxRvydLIgJZJid%2FStack-values-copy.png?alt=media&amp;token=5a0694cb-41de-4a48-a353-9b7516894b1b" alt=""><figcaption></figcaption></figure>

{% code lineNumbers="true" %}

```csharp
Fighter f = new Fighter(); // Instans skapas av klassen Fighter.
                           // Instansen lagras i heapen.
                           // Identifiern f skapas och pekar mot en plats i stacken.
                           // På den platsen finns en pekning till instansens plats
                           //  i heapen.

Fighter f2 = f; // Identifiern f2 skapas.
                // Det som finns på platsen i stacken som f pekar mot
                // kopieras till platsen som f2 pekar på.
                // Inget nytt objekt skapas i heapen – både f1 och f2 pekar mot
                //  samma objekt.
```

{% endcode %}

<div><figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2F5y8Tyt7RTetZHhlXMo4Y%2FStack-Heap-References-before-copy.png?alt=media&amp;token=0e445b59-3a5b-41e6-a27a-247989793c7b" alt=""><figcaption><p>Innan tilldelningen av f2 finns bara f, som pekar till en Fighter-instans i heapen.</p></figcaption></figure> <figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FtiwLbkM9YWZO7fqCkL1m%2FStack-Heap-References-copy.png?alt=media&amp;token=e209b26a-78b2-4be1-8106-a035d79c2866" alt=""><figcaption><p>Efter tilldelningen av f2 finns fortfarande bara en Fighter-instans; det som kopieras är innehållet i stacken – alltså pekaren.</p></figcaption></figure></div>

### Parametervärden

Ovanstående gäller också parametrar i metoder.

{% code lineNumbers="true" %}

```csharp
int k = 9;

TakeInt(k); // talet 9 kopieras från k-identifiern till i-identifiern.

static void TakeInt(int i)
{
  // variabeln i pekar mot sin helt egna kopia av talet 9.
}
```

{% endcode %}

{% code lineNumbers="true" %}

```csharp
Fighter f = new Fighter();

TakeFight(f); // Referensen till fighter-instansen kopieras från f till localFighter

Console.WriteLine(f.hp); // visar att f's hp-värde ändrades inuti metodenc

static void TakeFight(Fighter localFighter)
{
  // Variabeln localFighter pekar mot samma instans som variabeln f.
  localFighter.hp -= 9; // Ändrar på instansens hp-värde
}
```

{% endcode %}

## Out och ref

{% hint style="info" %}
**Varning:** Använd out och ref så lite som möjligt. Det är väldigt, väldigt lätt att göra fel med dem.
{% endhint %}

När en metod tar emot en parameter, är det i vanliga fall så att det man får en kopia av *värdet i stacken*.

Med out och ref kan man istället få en pekare till *platsen* i stacken – vilket gör att man inuti metoden kan ändra variabelns värden direkt.

Med andra ord – stoppar man in en variabel som ref eller out så får man vara beredd på att precis vad som helst kan ha hänt med den efteråt. Den kan ha fått ett helt nytt värde eller till och med, om det är en reference type-variabel, referera till ett helt annat objekt.

```csharp
static void WithoutRef(int x)
{
  x++;
}

static void WithRef(ref int x)
{
  x++;
}

static void WithOut (out int x)
{
  x = 0;
  x++;
}

int y = 3;

WithoutRef(y);
Console.WriteLine(y); // 3

WithRef(ref y);
Console.WriteLine(y); // 4

WithOut(out y);
Console.WriteLine(y); // 1
```

Ref och out fungerar i princip likadant, men det finns skillnader:

* Med out måste variabeln initieras inuti metoden. Man kan alltså inte ändra ett existerande värde – variabeln som stoppas in *kommer garanterat* att ges ett helt annat värde i metoden.
* Med ref måste variabeln redan vara initierad innan den stoppas in som ref. Man kan inte ref:a en variabel man skapar på plats. Med out kan man skapa variabeln i parenteserna vid anropet.

```csharp
// Fungerar:
int t = 6;
WithRef(ref t);

// Fungerar inte:
WithRef(ref int u);

// Fungerar:
WithOut(out int u);
```


# Projektstruktur

Ett C#-projekt består av ett antal textfiler. Några av dem innehåller själva C#-koden; andra innehåller information om hur den koden ska köras, vilken version av C# som ska användas och så vidare.

Oftast brukar C#-projektet också ingå i en *solution* – ett slags samling av ett eller flera projekt. När ett nytt projekt skapas genom C# Toolbox-tillägget så skapas både en solution, ett projekt i denna solution, och en första C#-fil i projektet.

## Mappstruktur

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FFrHYJsOzHACHyTCSM4or%2Fimage.png?alt=media\&token=2a480c9e-aed5-4170-bfaf-04aaea5d178c)

Mappen som skapas av C# Dev Kit har följande struktur:

* .vscode
* Mapp med projektet
  * obj
  * bin
  * csproj-fil
  * cs-filer
* sln-fil

**.vscode** är en mapp som Vidual Studio Code skapar för att hålla reda på sina egna inställningar – till exempel när filer för körning och debuggning skapas, eller när man sedan ändrar i de filerna (internalConsole --> externalTerminal).

**Mapp med projektet** – en mapp som får projektets namn och innehåller alla filer som hör till själva C#-projektet.

**obj-mappen** innehåller "mellanfiler" – filer som dotnet/C# skapar som ett mellanled mellan källkoden och de färdiga körbara filerna. Den kan tas bort, men kommer då att återskapas nästa gång projektet körs eller debuggas.

**bin-mappen** innehåller de körbara filer som dotnet/C# skapar utifrån källkoden. Det är filerna i den här mappen som är själva "programmet", och som man kan distribuera till andra människor och datorer.

**csproj-filen** innehåller information om C#-projektet.

**cs-filerna** innehåller själva C#-källkoden.

**sln-filen** är den fil som innehåller information om den *solution* som skapats.

## C#-projekt (csproj)

{% code lineNumbers="true" %}

```xml
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>
```

{% endcode %}

En csproj-fil är en XML-fil med information om C#-projektet. Varje bit information kallas för en *property*.

### Properties

Properties som är ifyllda från början:

* **OutputType** – vilken sorts fil projektet ska kompileras till. Här: en exe-fil (körbar fil i windows).
* **TargetFramework** – vilken version av dotnet / C# som ska användas. I exemplet är det dotnet 6.
* **ImplicitUsings** – huruvida man vill använda [implicita usings](https://csharp.progdocs.se/grundlaggande/pages/A35xLfE6MYObS3hXJxXb#implicit-using-.net-6).
* **Nullable** – Dotnet 6 introducerar "nullable reference types", något som mestadels märks i att man får varningar vid vanliga strings… Enklaste lösningen att hantera detta är att helt enkelt stänga av Nullable genom att kommentera bort raden eller ändra "enable" till "disable".

Man kan också lägga till fler properties, till exempel:

```xml
  <PublishSingleFile>true</PublishSingleFile>
  <PublishTrimmed>true</PublishTrimmed>
```

Dessa två gör så att när man kompilerar projektet så samlas allt man behöver i en enda exe-fil, och så att den filen bara innehåller det som absolut behövs för att köra programmet.

### PropertyGroup

I en csproj används \<PropertyGroup>-element för att klumpa ihop egenskaper (properties).

### ItemGroup

ItemGroup-element används för att gruppera properties som beskriver filer eller grupper av filer som ska inkluderas i projektet. Till exempel [externa bibliotek som lagts till via nuget](/grundlaggande/anvaenda-bibliotek-using#nuget-gallery) och [Resursfiler](/filhantering/resursfiler#losning-1-kopiera-filerna-automatiskt-till-malmappen).

```xml
  <ItemGroup>
    <PackageReference Include="Raylib-cs" Version="4.5.0.4" />
  </ItemGroup>
  
  <ItemGroup>
    <Content Include="*.png" CopyToOutputDirectory="Always"/>
  </ItemGroup>
```

## Dotnet-solutions (sln)

{% code lineNumbers="true" %}

```
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoProject", "DemoProject\DemoProject.csproj", "{FE320B4D-B077-4D3C-BBF4-306ADAA15842}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{FE320B4D-B077-4D3C-BBF4-306ADAA15842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{FE320B4D-B077-4D3C-BBF4-306ADAA15842}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{FE320B4D-B077-4D3C-BBF4-306ADAA15842}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{FE320B4D-B077-4D3C-BBF4-306ADAA15842}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
EndGlobal
```

{% endcode %}

SLN-filen innehåller en hel del information, där det viktigaste för oss är vilka projekt som ingår. I exemplet ingår ett enda projekt – "DemoProject".


# Dotnet i terminalen

Visual Studio Code är i grunden bara ett program för att redigera text – allt annat sköts egentligen av andra, separata program. När man programmerar i C# så är ett av de programmen **dotnet**.

* Varje gång ett program till exempel körs så anropar Code först dotnet för att omvandla källkoden till körbara filer.
* Varje gång C# Dev Kit används för att skapa ett nytt projekt anropas dotnet med olika tillval för att skapa en solution och ett nytt tomt C#-projekt.

Man kan också köra dotnet själv, manuellt i terminalen / kommandotolken. Egentligen behövs inte Visual Studio Code – man kan skriva sin kod i Anteckningar eller nästan vilket textredigeringsprogram som helst.

### Dotnet --list-sdks

Skriver ut en lista på vilka dotnet-versioner som är installerade på datorn.

```powershell
PS C:\Users\krank> dotnet --list-sdks
5.0.408 [C:\Program Files\dotnet\sdk]
6.0.302 [C:\Program Files\dotnet\sdk]
PS C:\Users\krank>
```

### Dotnet new

Skapa ett konsollprojekt (ProjectName.csproj) och tillhörande filer i nuvarande mapp:

```
dotnet new console --name ProjectName
```

"Console" anger vilken av dotnets inbyggda C#-projektmallar som används.

Skapa en solution (MySolution.sln) i nuvarande mapp:

```
dotnet new sln --name MySolution
```

### Dotnet run

Kompilerar och kör projektet i den nuvarande mappen (eller solutionens primära projekt):

```
dotnet run
```

### Dotnet add package

Lägger till ett nuget-paket till projektet.

```
dotnet add package Raylib-cs
```

### Dotnet restore

Laddar ner saknade nuget-bibliotek (t.ex. [Raylib](/annat/raylib)) som projektet använder. Väldigt användbart eftersom det betyder att de biblioteken inte måste skickas med till andra som ska jobba med projektet.

```
dotnet restore
```

### Dotnet sln add

Lägg till ett projekt (ProjectName.csproj) i den solution som finns i den nuvarande mappen:

```
dotnet sln add .\ProjectName\ProjectName.csproj
```


# Filsökvägar

## Filsökvägar

En filsökväg i windows kan t.ex. se ut så här:

```
c:\temp\exempel.txt
```

Det betyder:

* Filen finns på enhet C.
* I C finns det en mapp som heter temp.
* I mappen temp finns en fil som heter exempel.
* exempel-filens filändelse är txt.

Med andra ord används \ för att separera enheter, mappar och filnamn. I filnamn används punkt för att separera namn från filändelse.

Eftersom \ redan används som "escape"-tecken i C#, för att t.ex. göra radbrytning \n, så måste man ange filsökvägar så här:

```
string path = @"c:\temp\exempel.txt";
```

@-tecknet gör att \\-tecknen inte tolkas, utan [tas bokstavligt](/grundlaggande/datatyper/string#verbatim-strings).

### Filer i samma mapp som programmet <a href="#h.p_gkvdjqel-lgi" id="h.p_gkvdjqel-lgi"></a>

När det gäller filer som ligger i samma mapp som programmet så behöver man inte ange mapp eller enhet.

```
string path = @"localfile.txt";
```

För er som läst webbutveckling bör detta vara bekant.


# Läsa och skriva

## Att läsa data från en fil

Börja med att lägga till System.IO högst upp bland de bibliotek som inkluderas.

```csharp
using System.IO;
```

### ReadAllText()

Läser in all information från angiven fil till en string

```csharp
string contents = File.ReadAllText(@"localfile.txt");
```

Exempelkoden läser in all data från filen localfile.txt och lagrar datan i string-variabeln contents.

### ReadAllLines()

Läser in all information från angiven fil till en string-array — en rad från filen per position i arrayen.

```csharp
string[] contents = File.ReadAllLines(@"localfile.txt");
```

Exempelkoden läser in all data från filen localfile.txt och lagrar datan i string-array-variabeln contents.

Om localfile.txt t.ex. innehåller:

{% code title="localfile.txt" %}

```
Banana
Apple
Monkey
```

{% endcode %}

så kommer contents-arrayen att ha tre strings i sig: Banana, Apple och Monkey.

## Att skriva data till en fil

Börja med att lägga till System.IO högst upp bland de bibliotek som inkluderas.

```csharp
using System.IO;
```

### WriteAllText()

Skriver en string till en textfil.

```csharp
File.WriteAllText(@"localfile.txt", "Banana");
```

Exempelkoden skriver texten "Banana" till textfilen localtext.txt.

### WriteAllLines()

Skriver en string-array till en textfil - med en av arrayens strings per rad.

{% code lineNumbers="true" %}

```csharp
string[] contents = {"Apple", "Banana", "Monkey"};

File.WriteAllLines(@"localfile.txt", contents);
```

{% endcode %}

Exempelkoden skriver innehållet från string-arrayen contents till filen localfile.txt. Resultatet blir att localfile.txt innehåller följande:

{% code title="localfile.txt" %}

```
Apple
Banana
Monkey
```

{% endcode %}


# Filer och mappar

Alla dessa kräver att du först inkluderar System.IO i filen där du vill använda dem.

```csharp
using System.IO;
```

## Filer

### File.Delete()

Tar bort den fil som anges som parameter.

```csharp
File.Delete(@"localfile.txt");
```

### File.Exists()

File.Exists är en metod som returnerar true om filen som anges som parameter existerar, false om den inte gör det.

```csharp
if (File.Exists(@"localfile.txt"))
{
  Console.WriteLine("The file exists!");
}
```

## Mappar

### Directory.CreateDirectory()

Skapa en mapp.

```csharp
Directory.Create(@"Savegames");
```

### Directory.Delete()

Ta bort en mapp.

```csharp
Directory.Delete(@"Savegames");
```

### Directory.Exists()

Kolla om en mapp existerar.

{% code lineNumbers="true" %}

```csharp
if (Directory.Exists(@"Savegames")
{
  /* Stuff */
}
```

{% endcode %}

### Directory.GetFiles()

Hämta en array som innehåller alla filer som finns i en mapp.

{% code lineNumbers="true" %}

```csharp
foreach (string filename in Directory.GetFiles(@"Savegames")
{
  Console.WriteLine(filename);
}
```

{% endcode %}


# Open, close, using

## File.Open()

Används för att skapa en koppling till en fil .

```csharp
FileStream file = File.Open(@"test.txt", FileMode.OpenOrCreate); 
```

Variabeln file blir ett "FileStream"-objekt, som man kan använda för att skriva till eller läsa från filen, i det här fallet test.txt.

FileModes:

* FileMode.Open – öppna en fil som garanterat finns. Kasta felmeddelande FileNotFoundException om den inte finns.
* FileMode.OpenOrCreate – öppna en fil; skapa den om den inte finns.

## Close()

Används för att "stänga" en koppling till en fil och informera operativsystemet om att den nu kan öppnas och användas av andra program igen.

```
file.Close();
```

Det är en mycket bra idé att alltid komma ihåg att stänga sina filer när man är klar med dem.

## Using()

Using gör att man slipper använda Close() – när kodblocket är slut så stängs filen automatiskt.

{% code lineNumbers="true" %}

```
using (FileStream file = File.Open(@"test.txt", FileMode.OpenOrCreate))
{
  /* Gör saker */
}
```

{% endcode %}


# Serialisering \[…]

[JSON-serialisering](/filhantering/serialisering/json-serialisering) | [XML-serialisering](/filhantering/serialisering/xml-serialisering)

Serialisering handlar om att ta ett objekt – en [instans ](/klasser-och-objektorientering/klasser-och-instanser)– och göra om objektet till ren text (s.k. "plain text") som kan lagras i en fil eller till exempel skickas via internet.

För att den rena texten sen ska kunna avläsas (deserialiseras) tillbaka till ett objekt i andra änden så behöver man vara överens om ett format. JSON är idag ett av de absolut vanligaste, och XML är också förekommande.

Se nedan för ett exempel på en klass och hur en instans av klassen skulle se ut om man serialiserade den till JSON respektive XML.

{% tabs %}
{% tab title="Spaceship.cs" %}

```csharp
public class Spaceship
{
 public int Hp {get; set;} = 100;
 public int MaxHp {get; set;} = 100;
 public int Speed {get; set;} = 2;
}
```

{% endtab %}

{% tab title="Spaceship.json" %}

```javascript
{
  "Hp": 100,
  "MaxHp": 100,
  "Speed": 2
}
```

{% endtab %}

{% tab title="Spaceship.xml" %}

```markup
<?xml version="1.0"?>
<Spaceship xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <hp>100</hp>
 <maxHp>100</maxHp>
 <speed>2</speed>
</Spaceship>
```

{% endtab %}
{% endtabs %}


# JSON-serialisering

[JSON ](/filhantering/filformat/json)är Javascript Object Notation, så för den som är van vid Javascript kanske det ser bekant ut.

[Här hittar du Microsofts officiella dokumentation.](https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to)

## Bibliotek

Lägg till detta using-statement:

```csharp
using System.Text.Json;
```

## Klassdesign

Klassen vars instanser ska kunna serialiseras/deserialiseras måste vara public.

{% code title="Pokemon.cs" lineNumbers="true" %}

```csharp
public class Pokemon
{
  public string name {get; set;}
  public int id {get; set;}
  public bool is_default {get; set;}
}
```

{% endcode %}

Vad som inkluderas i serialiseringen är:

* Publika [properties](/klasser-och-objektorientering/inkapsling-och-properties#properties) med publika get och set
* Variabler och properties som det står \[JsonInclude] framför

Om du ska deserialisera JSON-kod som du får från något annat ställe och inte designat själv, så behöver du vara noga med att **matcha namnet** på dina publika variabler/[properties ](/klasser-och-objektorientering/inkapsling-och-properties#properties)mot JSON-kodens. Serialiseringsprocessen är normalt känslig vad gäller stora och små bokstäver, men du kan ändra på detta (rekommenderas!).

{% tabs %}
{% tab title="Pokemon.cs" %}

```csharp
public class Pokemon
{
  public string name {get; set;}
  public int id {get; set;}
  public bool is_default {get; set;}
}
```

{% endtab %}

{% tab title="Ditto.json" %}

```json
{
  "form_name": "",
  "form_names": [],
  "form_order": 1,
  "id": 132,
  "is_battle_only": false,
  "is_default": true,
  "is_mega": false,
  "name": "ditto",
  "names": [],
  "order": 198, 
  // (...)
}
```

{% endtab %}
{% endtabs %}

## JsonSerializer.Serialize<>() <a href="#jsonserializer.serialize" id="jsonserializer.serialize"></a>

Används för att serialisera ett objekt till en JSON-string.

{% code lineNumbers="true" %}

```csharp
Pokemon poke = new Pokemon()
{
  Name = "Ditto",
  Id = 132,
  IsDefault = true,
  Species = new PokemonSpecies() {
    Name = "ditto",
    Url = "https://pokeapi.co/api/v2/pokemon-species/132/"
  }
};

string json = JsonSerializer.Serialize<Pokemon>(poke);
```

{% endcode %}

Denna string kan sedan lagras i en textfil eller t.ex. skickas som svar på ett [REST](/annat/naetverk-och-internet/restful-client)-anrop.

### JsonSerializerOptions

Genom att skicka in ett JsonSerializerOptions-objekt kan man ge mer detaljerade instruktioner till serializern.

```csharp
JsonSerializerOptions options = new ()
{
  // Ger snygg, indenterad JSON-kod
  WriteIndented = true,
  // Omvandlar alla property-namn till snake_case
  PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower // döper om properties
};

string json = JsonSerializer.Serialize<Pokemon>(poke, options);
```

I JSON används oftast snake\_case, medan C# ju använder [camelCase eller PascalCase](/grundlaggande/namngivning#pascalcase-och-camelcase).

{% hint style="warning" %}
**OBS:** SnakeCaseLower introducerades i dotnet 8!
{% endhint %}

## JsonSerializer.Deserialize<>() <a href="#jsonserializer.deserialize" id="jsonserializer.deserialize"></a>

Används för att deserialisera ett objekt från en JSON-string.

{% code lineNumbers="true" %}

```csharp
// jsonString innehåller json-data. Den kan t.ex. läsas in från en json-fil
// eller hämtas från en REST-server.
Pokemon ditto = JsonSerializer.Deserialize<Pokemon>(jsonString);
```

{% endcode %}

## Attribut

Mer om attribut [här](/klasser-och-objektorientering/attribut).

{% hint style="warning" %}
**OBS:** dessa kräver att du inkluderar `System.Text.Json.Serialization`.
{% endhint %}

### \[JsonInclude]

Används för att inkludera en variabel eller property i Json-serialiseringen

```csharp
using System.Text.Json.Serialization;

public class Pokemon
{
  [JsonInclude]
  public string Name;
  
  [JsonInclude]
  public bool IsDefault;
}
```

### \[JsonIgnore]

Används för att se till så att en variabel eller property på C#-sidan inte serialiseras till JSON.

{% code title="Pokemon.cs" lineNumbers="true" %}

```csharp
using System.Text.Json.Serialization;

public class Pokemon
{
  public string Name {get; set;}
  public bool IsDefault {get; set;}
  
  [JsonIgnore]
  public int CurrentHp {get; set;}
}
```

{% endcode %}

### \[JsonPropertyName()]

Med attributet `[JsonPropertyName()]` kan man bestämma att en C#-klass' property ska matchas mot ett JSON-värde med annat namn.

{% code title="Pokemon.cs" lineNumbers="true" %}

```csharp
using System.Text.Json.Serialization;

class Pokemon
{
  public string Name {get; set;}
  public int Id {get; set;}
  
  [JsonPropertyName("is_default")]
  public bool IsDefault {get; set;}
}
```

{% endcode %}

## Deserialisering av listor

Ibland beskriver JSON-kod listor av objekt eller värden. De kännetecknas av att ge omges av hakparenteser `[]`.

{% code lineNumbers="true" %}

```json
{
  "name": "ditto",
  "forms":
  [
    "Ditto",
    "Exempel"
  ]
}
```

{% endcode %}

För att deserialisera dessa, skapa helt enkelt publika [listor ](/grundlaggande/listor-och-arrayer#list)i klassen.

{% code title="Pokemon.cs" lineNumbers="true" %}

```csharp
class Pokemon
{
  [JsonPropertyName("name")]
  public string Name {get; set;}
  
  [JsonPropertyName("forms")]
  public List<string> Forms {get; set;}
}
```

{% endcode %}

## Deserialisering av objekt i flera led

Ibland beskriver JSON-kod objekt som innehåller andra objekt.

{% code lineNumbers="true" %}

```json
{
  "name": "ditto",
  "species":
  {
    "name": "ditto",
    "url": "https://pokeapi.co/api/v2/pokemon-species/132/"
  }
}
```

{% endcode %}

För att deserialisera dessa, skapa klasser som beskriver de inre objekten.

{% code title="PokemonSpecies.cs" lineNumbers="true" %}

```csharp
class PokemonSpecies
{
  [JsonPropertyName("name")]
  public string Name {get; set;}
  
  [JsonPropertyName("url")]
  public string Url {get; set;}
}
```

{% endcode %}

{% code title="Pokemon.cs" lineNumbers="true" %}

```csharp
class Pokemon
{
  [JsonPropertyName("name")]
  public string Name {get; set;}
  
  [JsonPropertyName("species")]
  public PokemonSpecies Species {get; set;}
}
```

{% endcode %}


# XML-serialisering

## Bibliotek

Lägg till dessa using-statements:

{% code lineNumbers="true" %}

```csharp
using System.Xml.Serialization;
using System.IO;
```

{% endcode %}

## Klassdesign

Klassen vars instanser ska kunna serialiseras måste vara public.

{% code title="Spaceship.cs" lineNumbers="true" %}

```csharp
public class Spaceship
{
  // Lägg som vanligt in variabler, properties, metoder etc här
}
```

{% endcode %}

Det är också enbart publika variabler samt properties med publika getters och setters som serialiseras.

Om du ska deserialisera XML-kod som du får från något annat ställe och inte designat själv, så behöver du vara noga med att matcha namnet på dina publika variabler/[properties ](/klasser-och-objektorientering/inkapsling-och-properties#properties)mot XML-filens. Serialiseringsprocessen är dock inte känslig vad gäller stora och små bokstäver.

{% tabs %}
{% tab title="Spaceship.cs" %}
{% code lineNumbers="true" %}

```csharp
public class Spaceship
{
 public int Hp {get; set;} = 100;
 public int MaxHp {get; set;} = 100;
 public int Speed {get; set;} = 2;
}
```

{% endcode %}
{% endtab %}

{% tab title="Spaceship.xml" %}
{% code lineNumbers="true" %}

```markup
<?xml version="1.0"?>
<Spaceship xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <hp>100</hp>
 <maxHp>100</maxHp>
 <speed>2</speed>
</Spaceship>
```

{% endcode %}
{% endtab %}
{% endtabs %}

## XmlSerializer

För att kunna serialisera instanser till XML behövs en XML-serialiserare, specialbyggd för att serialisera instanser av just den klassen.

```csharp
XmlSerializer shipSerializer = new XmlSerializer(typeof(Spaceship));
```

Tyvärr är XmlSerializern inte skriven som en generisk klass, så istället måste man använda typeof för att meddela vilken klass det är serialiseraren ska specialisera sig på.

## Serialize()

När vi har en serialiserare så kan vi använda den för att serialisera en instans av en klass.

Beroende på om man vill ha ut XML-koden till en string eller till en fil behövs en StringWriter eller en FileStream.

{% tabs %}
{% tab title="StringWriter" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip = new Spaceship();

StringWriter textWriter = new StringWriter();

shipSerializer.Serialize(textWriter, myShip);

textWriter.Close();
```

{% endcode %}
{% endtab %}

{% tab title="FileStream" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip = new Spaceship();

FileStream file = File.Open(@"ship.xml", FileMode.OpenOrCreate);

shipSerializer.Serialize(file, myShip);

file.Close();
```

{% endcode %}
{% endtab %}
{% endtabs %}

Resultatet av denna kod blir att XML-koden längre upp på den här sidan sparas ner i ship.xml.

Samma kod kan skrivas så här, med hjälp av ett [using-statement](/filhantering/open-close-using#using):

{% tabs %}
{% tab title="StringWriter" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip = new Spaceship();

using (StringWriter textWriter = new StringWriter())
{
  shipSerializer.Serialize(textWriter, myShip);
}
```

{% endcode %}
{% endtab %}

{% tab title="FileStream" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip = new Spaceship();

using (FileStream file = File.Open(@"ship.xml", FileMode.OpenOrCreate))
{
  shipSerializer.Serialize(file, myShip);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Deserialize()

Serialiseraren kan också användas för att omvandla XML-text till en instans av klassen.

Beroende på om XML-koden finns i en string eller till en fil behövs en StringReader eller en FileStream.

{% tabs %}
{% tab title="StringReader" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip; // Variabeln resultatet lagras i

// xmlText är en variabel som innehåller XML-data
StringReader textReader = new StringReader(xmlText);

myShip = (Spaceship) shipSerializer.Deserialize(textReader);

textReader.Close();
```

{% endcode %}
{% endtab %}

{% tab title="FileStream" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip; // Variabeln resultatet lagras i

// ship.xml är en fil som innehåller XML-data
FileStream file = File.Open(@"ship.xml", FileMode.OpenOrCreate);

myShip = (Spaceship) shipSerializer.Deserialize(textReader);

file.Close();
```

{% endcode %}
{% endtab %}
{% endtabs %}

Eftersom serializern inte är skriven som en generisk klass så måste vi aktivt casta det Deserialize returnerar till den klass vi vill att det ska vara (och vet att det borde vara), i det här fallet Spaceship.

Samma kod kan skrivas så här, med hjälp av ett [using-statement](/filhantering/open-close-using#using):

{% tabs %}
{% tab title="StringReader" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip;

using (StringReader textReader = new StringReader(xmlText))
{
  myShip = (Spaceship) shipSerializer.Deserialize(textReader);
}
```

{% endcode %}
{% endtab %}

{% tab title="FileStream" %}
{% code lineNumbers="true" %}

```csharp
Spaceship myShip;

using (FileStream file = File.Open(@"ship.xml", FileMode.OpenOrCreate))
{
  myShip = (Spaceship) shipSerializer.Deserialize(textReader);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## XML-serialisering av samlingar (arrayer, listor)

Det går utmärkt att serialisera även listor.

{% code lineNumbers="true" %}

```csharp
List<Spaceship> fleet = new List<Spaceship>();

fleet.Add(new Spaceship());
fleet.Add(new Spaceship());
fleet.Add(new Spaceship());

XmlSerializer fleetSerializer = new XmlSerializer(typeof(List<Spaceship>));

using (FileStream file = File.Open(@"fleet.xml", FileMode.OpenOrCreate))
{
  shipSerializer.Serialize(file, fleet);
}
```

{% endcode %}

Precis som med andra variabler och properties så kommer publika samlingar av instanser som lagrats i en instans också serialiseras.

{% tabs %}
{% tab title="Fleet.cs" %}
{% code lineNumbers="true" %}

```csharp
public class Fleet
{
  public List<Spaceship> ships = new List<Spaceship>();
}
```

{% endcode %}
{% endtab %}

{% tab title="Fleet.xml" %}
{% code lineNumbers="true" %}

```markup
<?xml version="1.0"?>
<Fleet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <ships>
   <Spaceship>
     <hp>100</hp>
     <maxHp>100</maxHp>
     <speed>2</speed>
   </Spaceship>
   <Spaceship>
     <hp>100</hp>
     <maxHp>100</maxHp>
     <speed>2</speed>
   </Spaceship>
 </ships>
</Fleet>
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Resursfiler

Ofta jobbar vi med filer som ska finnas i samma mapp som vårt program, eller i en filsökväg relativt programmet. Till exempel:

* Json-filer som ska sparas till eller läsas in
* Bildfiler som Raylib ska läsa in och rita till skärmen
* Textfiler som innehåller spelets berättelse

Dessa letar programmet alltid efter i den nuvarande mappen (**current folder**). Vad som räknas som current folder varierar.

* Använder man en utförlig launch.json (via t.ex. [Generate assets…](/lathund-skapa-projekt)) så är current folder **mappen csproj-filen ligger i**.
* Använder man den ganska tomma default-launch-json-filen som C# Dev Kit numera skapar, så är current folder mappen som den kompilerade exe/dll-filen ligger i.

## Lösning 1: Kopiera filerna automatiskt till målmappen

Det här är **det rekommenderade sättet** att lösa problemet på.

Öppna projektets csproj-fil. Den bör se ut ungefär såhär:

```xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <!-- <Nullable>enable</Nullable> -->
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Raylib-cs" Version="4.5.0.4" />
  </ItemGroup>
</Project>
```

Lägg till en ny ItemGroup, till exempel direkt under den PropertyGroup som redan finns. I den nya ItemGroup:en lägger du in nya Content-element för de filer du vill ha med.&#x20;

```xml
  <ItemGroup>
    <Content Include="character.png" CopyToOutputDirectory="Always"/>
    <Content Include="tree.png" CopyToOutputDirectory="Always"/>
  </ItemGroup>
```

### Många filer av samma typ

För att kopiera alla filer av en viss typ kan du använda \*-tecken.

```xml
  <ItemGroup>
    <Content Include="*.png" CopyToOutputDirectory="Always"/>
  </ItemGroup>
```

### En hel mapp

Skapa en mapp där du lägger alla bilder, textfiler och annat du vill ha med. Döp den till t.ex. Assets.

Gör så att mappen, inklusive alla undermappar och filer, kopieras:

```xml
  <ItemGroup>
    <Content Include="Assets\**\*.*" CopyToOutputDirectory="Always"/>
  </ItemGroup>
```

## Lösning 2: Lägg filerna manuellt till målmappen

* Lägg alla nödvändiga filer direkt till mappen där exe/dll:en ligger. Kör du dotnet 7 blir det i **bin\Debug\net7.0**.
* Kom ihåg att inte ta bort mappen utan att vara säker på att du har kopior av filerna!
* Kom ihåg att kopiera in samma filer i din exe-fils mapp när du [kompilerar för publicering](/kompilering-och-publicering)!


# Filformat


# JSON

JSON är Javascript Object Notation, så för den som är van vid Javascript kanske det ser bekant ut.

## Datatyper

Det finns fem datatyper i JSON:

* **string** – "test"
* **number** – 42
* **bool** – true
* **array** – \[]
* **object** – {}

## Objekt och egenskaper

Objekt kan innehålla **egenskaper**. Varje egenskap har ett **namn** och ett **värde**. Värdet är en av de fem datatyperna. Egenskapsnamnen är **strings**. Man separerar egenskaperna från varandra med **kommatecken**, och separerar egenskapsnamn från egenskapsvärde med **kolon**.

```json
{
  "name": "Albert",
  "age": 3000
}
```

En egenskap kan ha ett objekt som värde:

```json
{
  "name": "Albert",
  "age": 3000,
  "weapon": {
    "name": "Sword",
    "damage": 300
  }
}
```

## Arrayer

En array kan innehålla flera värden. Värdena är oftast av samma datatyp, men måste inte vara det.

```
["Sword", "Shield", "Socks"]
```

```
[66, 32, "black hole", true]
```

I Javascript kommer man sedan åt varje position i arrayen genom att hänvisa till dess position, som anges som ett heltal. Den första saken i listan får nummer 0.

Skillnaden mellan en array och ett objekt är med andra ord att arrayer är [indexerade ](/grundlaggande/listor-och-arrayer#indexering)med *heltal* – så varje sak i listan identifieras med ett nummer – medan objects är indexerade med *strings*.

## Nästling

I JSON är det vanligt att lägga objekt i andra objekt, och objekt i listor, och listor i objekt.

Exempel på objekt i en array:

```json
[
  {
    "name": "Axe",
    "damage": 20
  },
  {
    "name": "Bazooka",
    "damage": 9001
  }
]
```


# Översikt objektorientering

## Objekt

Ett objekt är en samling variabler, metoder och algoritmer som "hör ihop" och motsvarar en "sak" i programmet.

*Exempel på objekt: Ett svärd, en fiende, en bok, en bana, ett päron, en kund.*

## Klass

En klass är en ritning, eller en mall, för en kategori av objekt. En klass är inte i sig ett objekt, utan bara en instruktion för hur ett objekt ska se ut och fungera.

*Exempel på klasser: Svärd, fiende, bok, bana, päron, kund.*

En klass fungerar också som en datatyp, så varje gång kod förväntar sig en datatyp (t.ex. string eller int) kan man istället skriva dit en klass.

[Mer om klasser.](/klasser-och-objektorientering/klasser-och-instanser#skapa-klasser)

## Instans

En instans är ett *objekt* man skapat utifrån en *klass*.

[Mer om instanser.](/klasser-och-objektorientering/klasser-och-instanser#skapa-instanser)

## Klassvariabler och klassmetoder

En klassvariabel är en variabel som ingår i en klass, och en [klassmetod ](/klasser-och-objektorientering/klassmetoder)är en metod som ingår i en klass.

Alla instanser av en klass får tillgång till alla klassens metoder och egen kopia av alla klassens variabler.

*Exempel:*

{% code title="" lineNumbers="true" %}

```csharp
class Pear
{
  public int Cost = 100; // <-- klassvariabel
  public bool Eaten = false; // <-- klassvariabel
  
  public void Eat() // <- klassmetod
  {
    eaten = true;
  }
}
```

{% endcode %}

## Arv

En klass kan [ärva ](/klasser-och-objektorientering/arv)från en annan klass. Det betyder att subklassen får basklassens alla metoder och variabler, men den kan också lägga till egna.

Man brukar också beskriva det som att subklassen är en mer specialiserad version av basklassen – ett exempel på basklass kan vara `Weapon` och en subklass till Weapon kan då vara `Sword`. Sedan kan Sword agera basklass till `LongSword` och `ShortSword`. Relationen mellan subklass och basklass är att \[subklassen] är en sorts \[basklassen], så att ShortWord är en sorts Weapon till exempel.

Alla svärd är då vapen, och har alla metoder etc som ingår i vapen – fast de kan ha egna tillägg, och de kan också delvis fungera annorlunda (se [Polymorfism](/klasser-och-objektorientering/polymorfism)).

## Komposition

Man kan också lägga in instanser av en klass i instanser av en annan klass. Detta kallas [komposition](/klasser-och-objektorientering/komposition).

Man brukar också beskriva det som att klassernas relation blir en *har-en-relation*. En hjälte *har ett* vapen (klassen Hero har en Weapon-variabel som innehåller instanser av den klassen eller dess subklasser).

## Inkapsling

[Inkapsling ](/klasser-och-objektorientering/inkapsling-och-properties)är principen att varje objekt – varje klass – ska sköta sin egen logik. Det innebär att man samlar all kod som hör ihop med ett objekt inuti metoder i objektets klass.

Det innebär också att man har så få variabler, properties och metoder som är publika. Man vill visa upp ett så litet "gränssnitt" mot resten av världen som möjligt.

Framför allt bör man, om man jobbar med inkapsling, inte ha några publika variabler. Istället används properties och metoder för att ändra på variablernas värde.

Anledningen till att man gör detta är dels för att skapa en tydlig struktur, dels minska risken att man gör fel när man skriver kod. Om det inte går att ändra på de privata variablerna direkt så kan man heller inte råka t.ex. ge dem ett felaktigt värde.

## Interaktion mellan objekt

När två objekt interagerar direkt med varandra, till exempel när data från ett objekt förs över till ett annat, eller när ett objekt stoppas in som parametervärde in i ett annat objekts metod.

{% code lineNumbers="true" %}

```csharp
Fighter hero = new Fighter();
Fighter opponent = new Fighter();

hero.Attack(opponent);
opponent.Attack(hero);
```

{% endcode %}

## Polymorfism

[Polymorfism ](/klasser-och-objektorientering/polymorfism#polymorfism-klasser-och-arv)i objektorientering är när en instans av en subklass lagras i en variabel eller t.ex. en lista vars datatyp är subklassens basklass. Så om man har subklassen Goomba som ärver från Monster, och lagrar en Goomba-instans i en Monster-variabel eller lägger in den i en Monster-lista så använder man polymorfism.

## Generiska klasser

[Generiska klasser](/klasser-och-objektorientering/generiska-klasser) är klasser där datatypen för en eller flera variabler eller metoder inte bestämts, utan avgörs när man skapar en instans av klassen. Ett exempel på färdig generisk klass är List.


# Lathund för klassdesign

## Klasser

* Vilka SAKER finns i programmet/spelet?
  * Spelarkaraktär, Fiender, Powerups, Andra objekt, Level/spelplan, Grafiska knappar
* Varje klass ska ha namn i **singular**, även om det finns flera i programmet/spelet.
  * Powerup, Player, Enemy, Football, BaseballBat
* Varje klass beskriver en **kategori** av saker.

### Underkategorier

* Är det liten skillnad mellan sakerna? Använd olika **instanser av samma klass**.
* Är det stor skillnad, framför allt i metoderna? Skapa nya klasser och använd **arv**.

### Variabler

* Vilka EGENSKAPER hos de olika sakerna är relevanta för spelet?
  * Position, Styrka, intelligens, Hit points
* En egenskap som bara är ett enkelt värde (int, strint, float etc) bör vara en **variabel**.
  * Exempel: namn, hit points
* En egenskap som är mer komplex, och i sig har en massa egenskaper/funktionalitet bör vara en referens till en **instans av en klass**.
  * Exempel: ett svärd, som har skadevärde, vikt etc
* Variabler kan leda till djupa hierarkier.
  * I en instans av klassen Game finns en instans av Scene, i instansen av Scene finns en instans av Player…

### Metoder

* Vilken kod hör samman med varje SAK?
  * Vilken kod använder enbart eller mestadels variabler som tillhör klassen?
* Vad ska varje SAK kunna göra?
* Metoder = verb, saker man kan göra med en instans eller som instansen kan göra.

### Public/private/protected

* Public, private och protected används för att skapa **gränssnittet ut mot världen**.
* Saker som ska kunna kommas åt utifrån – **public**.
  * Variabler – helst inte public alls. Använd [properties](/klasser-och-objektorientering/inkapsling-och-properties) istället.
* Saker som bara ska kunna påverkas från metoder som tillhör den här klassen – **private**.
* Saker som ska kunna påverkas av metoder som tillhör den här klassen och klasser som ärver från den – **protected**.


# Klasser och instanser

Klasser är ett sätt att klumpa ihop variabler och metoder som hör till samma "sak" i ett spel eller ett program. De gör det lättare att felsöka och lättare att hålla god struktur.

Man kan betrakta en **klass** som en ritning för något - "såhär ska fiender i spelet se ut - de ska ha de här egenskaperna".

Sedan skapar man **instanser** av klassen - de konkreta, faktiska fienderna. Alla goombas i Super Mario Bros och alla paladiner i World of Warcraft bygger på samma ritning. De har samma egenskaper och utseende i grunden, även om de skiljer sig åt i vilka värden en del av egenskaperna har. De befinner sig till exempel på olika positioner, även om de alla *har* en position.

## Skapa klasser

Generellt bör varje klass läggas i sin egen fil. Med C# Dev Kit finns ett snabbt och enkelt sätt:

* **Variant 1:** Tryck **Ctrl+Alt+Win+n**
  * Välj **.NET new file** i listan
* **Variant 2:** Gå till **kommandopaletten** (F1 eller **Ctrl+Shift+p**)&#x20;
  * Sök efter **.NET new file**
* Tryck **Enter** för att välja att lägga den nya filen **i ditt projekt**.
* Välj **"Class"**.
* Skriv in namnet på klassen – glöm inte [namngivning ](/grundlaggande/namngivning)med **PascalCase**!
* Skriv in skriv in **using** och namnet på klassens **namespace** högst upp i Program.cs

{% code title="Goomba.cs" lineNumbers="true" %}

```csharp
namespace PlumberPlatformer

class Goomba
{
  // Klassvariabler
  public int X = 0;
  public int Y = 0;
  public bool IsDead = false;
}
```

{% endcode %}

{% code title="Program.cs" %}

```csharp
using PlumberPlatformer;

```

{% endcode %}

## Skapa instanser

Kodordet `new` skapar **nya instanser** i minnet ([heapen](/grundlaggande/reference-vs-value-types#minnet-stacken-och-heapen)).

Därefter behöver en [referens ](/grundlaggande/reference-vs-value-types)till instansen lagras någonstans, till exempel i en variabel.

{% code lineNumbers="true" %}

```csharp
Goomba g1 = new Goomba();
Goomba g2 = new Goomba();
```

{% endcode %}

Därefter kan man ändra på de individuella instansernas variabler separat:

{% code lineNumbers="true" %}

```csharp
g1.X = 60;
g1.Y = 20;
g2.X = 80;
g2.Y = 25;
```

{% endcode %}

Man kan också tilldela värden till variablerna direkt när instansen skapas:

```csharp
Goomba g3 = new Goomba() {x = 10, y = 6};
```

### New()

Om man (som ovan) skapar en instans av exakt samma klass som variabeln så kan koden förenklas. Det gäller med andra ord nästan jämt – undantaget är vid [polymorfism](/klasser-och-objektorientering/polymorfism#polymorfism-klasser-och-arv).

{% code lineNumbers="true" %}

```csharp
Goomba g4 = new();
Goomba g5 = new() {X = 100};
```

{% endcode %}


# Struct

Structs är som klasser men skiljer sig på en viktig punkt: de är [value types snarare än reference types](/grundlaggande/reference-vs-value-types).

```csharp
Hero h1 = new() { Name = "A1" };
Hero h2 = h1; // h2 blir en KOPIA av h1, inte en pekare till samma objekt
h2.Name = "A2";

Console.WriteLine(h1.Name); // Så när namnet på h2 byts, så påverkas inte h1.
Console.WriteLine(h2.Name);

struct Hero
{
  public string Name;
}
```

Den generella regeln [som rekommenderas](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct) i C# är:

* Klasser om du vill inkludera beteende eller ha innehåll som förändras (lätt att låta flera delar av programmet arbeta med samma objekt).
* Structs för små objekt, utan speciellt mycket beteende och med ganska oföränderlig data.

Arbetar man med structs finns risk att man använder mer minne – eftersom man gör kopior av structen varje gång den överförs någonstans.


# Public, private och protected

## Public

Variabler och metoder som är **publika** kan läsas av och ändras på **utifrån**.

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  public string Name = "";
}
```

{% endcode %}

{% code title="Program.cs" lineNumbers="true" %}

```csharp
Fighter hero = new Fighter();
hero.Name = "Laban";
```

{% endcode %}

## Private

Variabler och metoder som inte är publika kan inte nås utifrån – men däremot kan de fortfarande nås **inifrån** metoder som ingår i samma klass. **Privata** variabler och metoder kan bara nås från metoder i **exakt** samma klass – så inte i någon subklass som ärver från den.

Om det **inte står något** framför en klassvariabel eller klassmetod är den **automatiskt private**.

För att man ska kunna få ut värdet hos en privat variabel behöver man gå via en publik metod som returnerar dess värde. Metoden tillhör ju klassen, så *den* får komma åt den privata variabeln. Detta är en form av [inkapsling](/klasser-och-objektorientering/inkapsling-och-properties).

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  private string _name = "";
  
  public string GetName()
  {
    return _name;
  }
}
```

{% endcode %}

## Protected

Fungerar som private, men metoden/variabeln kan kommas åt i klasser som *ärver* från klassen där de deklareras.

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  protected string _name = "";
  
  public string GetName()
  {
    return _name;
  }
}
```

{% endcode %}

{% code title="StrongFighter.cs" lineNumbers="true" %}

```csharp
class StrongFighter : Fighter
{
  public string GetName()
  {
    // kan använda name trots att variabeln tillhör basklassen
    return $"{_name} The Strong";
  }
}
```

{% endcode %}


# Klassdiagram

Ett klassdiagram beskriver hur en klass är strukturerad, och ser likadant ut oavsett programmeringsspråk. Diagrammet här skulle t.ex. kunna omvandlas till kod i Java, C#, PHP eller vilket annat språk som helst som har objektorientering.

I ett klassdiagram beskrivs klassen i tre sektioner:

* Klassnamnet — i det här fallet "Character".
* Variabler — i det här fallet hp och name.
* Metoder — i det här fallet Hurt och Attack.

**Variablerna:** Skrivs med namn och datatyp, men aldrig värde. Oftast skriver man namnet först, sedan kolon, och slutligen datatypen.

**Metoderna:** Skrivs med namn, parametrar och returtyp, men aldrig funktion. Oftast skriver man namnet först, sedan parametrarna inom parentes (i samma form som man skrev variablerna), och slutligen vilken datatyp metoden returnerar.

**Synlighet:** Man anger synlighet för variabler och metoder genom att skriva +, - eller # innan namnet.

* \+ betyder "public"
* − betyder "private"
* \# betyder "protected"&#x20;

{% @mermaid/diagram content="%%{init: {'theme': 'base', 'themeVariables':
{ 'primaryBorderColor': 'black',
'primaryColor': 'white'
}}}%%

classDiagram
class Character{
−\_hp : int
−\_name : string
\+  Hurt(amount : int) void
\+ Attack() int
}" %}

## Arv i klassdiagram

För att visa [arv ](/klasser-och-objektorientering/arv)i klassdiagram används pilar.

Pilarna pekar alltid FRÅN subklassen TILL basklassen. Man kan tänka sig att pilen betyder "är en sorts" eller "ärver från".

Subklassernas diagram ritas på samma sätt som basklassens. Man skriver in klassens variabler och metoder, inklusive metoder som använder [override](/klasser-och-objektorientering/polymorfism/virtual-override). Däremot skriver man inte in variabler eller metoder som bara ärvs från basklassen.

{% @mermaid/diagram content="%%{init: {'theme': 'base', 'themeVariables':
{ 'primaryBorderColor': 'black',
'primaryColor': 'white'
}}}%%

classDiagram
class Character{
−\_hp : int
−\_name : string
+Hurt(amount : int) void
+Attack() int
}
class Hero{
−\_xp : int
+GetLevel() int
}
Character <|-- Hero" %}

## Komposition i klassdiagram

För att visa komposition i klassdiagram används en pil som avslutas i en romb.

Rombpilarna pekar alltid FRÅN del-klassen TILL huvud-klassen. Man kan tänka sig att pilen betyder "ingår i", så att den ena klassen "ingår i" den andra klassen.

{% @mermaid/diagram content="%%{init: {'theme': 'base', 'themeVariables':
{ 'primaryBorderColor': 'black',
'primaryColor': 'white'
}}}%%

classDiagram
class Character{
−\_hp : int
−\_name : string
-\_weapon : Weapon
+Hurt(amount : int) void
+Attack() int
}
class Weapon{
−minDamage : int
−maxDamage : int
+Attack(target: Character) void
}
Character o-- Weapon" %}

### Överkurs

Ibland görs skillnad mellan *komposition* och *aggregering*. Skillnaden är då att man med komposition menar att de kopplade klasserna bara finns i huvudklassen och är integrerade delar av den – relationen är inte bara "ingår i" utan "är en del av". Aggregering är då namnet man ger den lösare typen av koppling.

{% @mermaid/diagram content="%%{init: {'theme': 'base',
'themeVariables':
{ 'primaryBorderColor': 'black',
'primaryColor': 'white'
}}}%%

classDiagram
class Character{
−\_hp : int
−\_name : string
+Hurt(amount : int) void
+Attack() int
}
class Inventory{
−\_item: List<Item>
+Add(item: Item)
+Remove(item: Item)
}
class Weapon{
−minDamage : int
−maxDamage : int
+Attack(target: Character) void
}
Character o-- Weapon
Character \*-- Inventory
" %}

## Vanliga frågor

* **Har man med variablers värde?** Nej, bara datatyp, namn och access modifier (public, private, protected)
* **Har man med metoders innehåll?** Nej, bara datatyp (returtyp), namn, parametrar (med namn och datatyp) och access modifier.
* **Hur gör man med listor?** Precis som vanligt, en int-listas datatyp skrivs som "List\<int>".
* **Hur gör man med properties?** Man kan lista dem som vanliga klassvariabler. NClass visar dem i metod-sektionen, kompletta med get och set. Det är också helt OK.

## NClass

NClass är ett enkelt program för att skapa klassdiagram. Det är gratis och [kan laddas ner här](https://github.com/gbaychev/NClass/releases).

{% hint style="info" %}
**Observera:** Länken leder till en ny fork av den gamla versionen av NClass. Den nya verkar utvecklas aktivt och har t.ex. stöd för Ctrl+Z och nyare projekt i sin code generation (Visual Studio 2019… Fortfarande inte Dotnet 5/6 tyvärr)
{% endhint %}


# Klassmetoder

Det går utmärkt att lägga in metoder i klasser. De anropas då genom att man skriver instansens namn följt av metodens namn, och lägger in parametrar och hanterar returneringar som vanligt.

Klassmetoders kod kan komma åt instansens variabler, properties och metoder. Det gäller även sådana den fått genom [arv](/klasser-och-objektorientering/arv).

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  private string _name = "";
  public string GetName()
  {
    return _name;
  }
}
```

{% endcode %}

{% code title="Program.cs" lineNumbers="true" %}

```csharp
Fighter f1 = new Fighter();

string n = f1.GetName();
Console.WriteLine(n);
```

{% endcode %}

När en metod som ingår i en klass vill använda en variabel som ingår i samma klass så kan den göra detta genom att använda dess namn rakt av. Man behöver alltså inte skriva instansens namn.

Om man vill vara tydlig med att man använder en intern klassvariabel så kan man skriva **this.** framför.

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  private string _name = "";
  
  public void WriteName()
  {
    Console.WriteLine(this._name);
  }
}
```

{% endcode %}


# Konstruktorer

En konstruktor är en metod som anropas automatiskt när en instans skapas. Den skrivs in i klassen som en publik metod utan returtyp och med samma namn som klassen.

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  private string _name = "";
  private int _strength = 0;

  public Fighter()
  {
    _strength = Random.Shared.Next(5,10);
  }
}
```

{% endcode %}

När man skapar en instans av klassen Fighter så ges instansen nu enligt koden ovan ett slumpat strength-värde.

## Parametrar och konstruktorer

Precis som andra metoder kan konstruktorer ta emot en eller flera parametrar. Det brukar till exempel användas som ett snabbt och enkelt sätt att skjuta in information som ska lagras i instansens variabler.

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  private string _name = "";
  private int _strength = 0;

  public Fighter(string name)
  {
    _name = name;
    strength = Random.Shared.Next(5,10);
  }
}
```

{% endcode %}

{% code title="Program.cs" lineNumbers="true" %}

```csharp
Fighter heroFighter = new Fighter("Britta-Lena");
Fighter enemyFighter = new Fighter("Börje");
```

{% endcode %}

## Kontruktorer som anropar varandra (this)

Om man har flera konstruktorer så väljs vilken som körs genom samma principer som annan [metod-överlagring](/grundlaggande/metoder#overlagring). Vill man själv kalla på en annan konstruktor så kan man göra detta genom att skriva :this() efter konstruktorns parenteser. Mellan de nya parenteserna lägger man de värden som ska passeras till önskad konstruktor.

```csharp
public class Fighter
{
  private int _hp;

  public Fighter(): this(100)
  {
  }

  public Fighter(int hp)
  {
    _hp = hp;
  }
}
```

## Konstruktorer i arv

När en basklass och en subklass har varsin konstruktor så kommer *båda* konstruktorerna att köras när en instans av subklassen skapas. Först körs basklassens konstruktor, därefter körs subklassens konstruktor.

{% code title="" lineNumbers="true" %}

```csharp
class Character
{
  protected int _hp;
  protected string _name = "";
  
  public Character()
  {
    _hp = 100;
  }
}
```

{% endcode %}

{% code title="Thief.cs" lineNumbers="true" %}

```csharp
class Thief: Character
{
  public Thief()
  {
    _name = "Thief";
    _hp = 20;
  }
}
```

{% endcode %}

I exemplet ovan kommer med andra ord en instans av Thief först 100 i hp när basklassens konstruktor körs, och sedan ändras hp till 20 och name till "Thief".

## Konstruktorer med parametrar i arv

Eftersom både basklassens och subklassens konstruktor körs, så betyder det att om basklassens konstruktor kräver ett parametervärde så måste det värdet stoppas in på något sätt även när det är subklassen som instansieras.

I exemplet nedan måste Character-klassens konstruktor få ett string-värde som parameter.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  public string _name;
  public int _hp = 100;

  public Character(string name)
  {
    _name = name;
  }
}
```

{% endcode %}

För att ange vilket värde som ska skickas till basklassens konstruktor så använder man base().

```csharp
class Dragon : Character
{
  public Dragon() : base("Dragon")
  {
    _hp = 200;
  }
}
```

Man kan också skicka vidare värden från subklassens konstruktor-parametrar till basklassens konstruktor.

{% code title="Hero.cs" lineNumbers="true" %}

```csharp
class Hero : Character
{
  public Hero(string name, int hp) : base(name)
  {
    _hp = hp;
  }
}
```

{% endcode %}

Här tar subklassens konstruktor emot två parametrar – name och hp – och skickar vidare värdet som lagras i parametern name till basklassens konstruktor.

## Primära konstruktorer (.net 8)

I dotnet 8 introduceras *primary constructors* – de gör att man kan stoppa in parametervärden in i klassen utan att explicit skapa en konstruktor.

```csharp
public class Enemy (string name, int hp)
{
  private int _hp = hp;
  private string _name = name;
}
```

Om man då stoppar in andra, vanliga konstruktorer så måste man modifiera dem så att de matar "primärkonstruktorn" med rätt data.

```csharp
public class Enemy(string name, int hp)
{
  private int _hp = hp;
  private string _name = name;

  // Konstruktor som körs när man inte anger några parametervärden: new Enemy()
  public Enemy() : this("Goomba", 100)
  {
  }

  // Konstruktor som körs när man anger bara en string, som förs vidare in i
  //  primärkonstruktorn
  public Enemy(string name) : this(name, 50)
  {
  }
}
```


# Arv

När man bygger en klass som bygger på en annan klass så kallas det **arv**. Arvet innebär att subklassen får samma variabler och metoder som basklassen. Arv är alltså ett sätt att *återanvända kod*.

{% hint style="info" %}
**OBSERVERA:** Arv symboliserar en "är-en-relation", det vill säga subklassen ska kunna sägas vara en underkategori till basklassen. En Hero *är en* sorts Character. En Goomba *är en* sorts Enemy. Ett svärd *är en* sorts vapen.
{% endhint %}

Man skapar ett arv genom att skriva ett kolon (:) efter klassnamnet, följt av namnet på basklassen. Så om man vill att klassen Hero ska ärva från klassen Character så skriver man `class Hero: Character` när man skapar klassen.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  public string name;
  public int hp = 100;
  public int x = 0;
  public int y = 0;

  public void Hurt(int amount)
  {
    hp -= amount;
  }
}
```

{% endcode %}

{% code title="Hero.cs" lineNumbers="true" %}

```csharp
class Hero: Character
{
  int _xp = 0;
  int _level = 1;
  
  public AddExperience(int amount)
  {
    _xp += amount;
    _level = 1 + _xp / 10;
  }
}
```

{% endcode %}

{% code title="Program.cs" lineNumbers="true" %}

```csharp
Hero myHero = new Hero();

myHero.name = "Britt-Marie";

myHero.Hurt(3);
myHero.AddExperience(12);
```

{% endcode %}

Hero bygger på Character, så alla instanser av Hero-klassen har egna name, hp, x och y-variabler. Dessutom har de egna kopior av Hurt-metoden, som då påverkar Hero-instansens egen hp.

Dessutom tillför Hero-klassen ett par egna variabler och en egen metod.


# Komposition

När ett objekt skapas och får sin funktionalitet genom att instanser av flera olika klasser samlas, så kallas det **komposition**. Komposition är, liksom arv, ett sätt att återanvända kod.

{% hint style="info" %}
**OBSERVERA:** Den relation som en komposition symboliserar är en "har-en-relation". En karaktär *har ett* vapen, en karaktär *har en* karaktärsklass. Medan "krigare" till exempel snarare *är en* karaktärsklass.
{% endhint %}

Komposition skapas genom att man helt enkelt lägger in klassvariabler eller properties vars datatyp är en klass som beskriver något instanser av klassen *har*.

```csharp
public class CharClass
{
  public string name;
}

public class Warrior : CharClass // Arv
{
  public Warrior()
  {
    name = "Warrior";
  }
}

public class Weapon
{
  public string name;
  public int minDamage;
  public int maxDamage;
}
```

```csharp
public class Character
{
  public string name;
  public int hp;
  public Weapon mainWeapon = new Weapon(); // Komposition
  public CharClass charClass = new Warrior(); // Komposition
}
```


# Inkapsling och properties

Inkapsling innebär egentligen inte nödvändigtvis någon ny kod, utan är ett grundläggande tankesätt:

* **Exponera så lite som möjligt.**

Det här innebär att man undviker att ha variabler som är direkt tillgängliga utanför klassen - i princip ska inga variabler vara public, utan de ska alla vara private eller protected.

Istället används metoder för att läsa av och ändra på variablerna.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  private int _hp = 100;

  public void SetHp(int hp)
  {
    _hp = hp;
  }

  public int GetHp()
  {
    return _hp;
  }  
}
```

{% endcode %}

I exemplet ovan kan man fortfarande få tag i karaktärers hp utifrån, och även bestämma nya värden, men man måste gå via GetHp och SetHp. Den här sortens metoder, som används för att direkt läsa av eller bestämma en variabels värde, kallas *getters* och *setters*.

En fördel med det här är att man kan välja att en variabel t.ex. enbart ska kunna läsas av - inte ändras utifrån. Då skapar man helt enkelt bara en getter och ingen setter.

En annan finess är att man får mer kontroll över vilka värden som ges till en variabel. I exemplet nedan hindras till exempel hp-värdet från att bli lägre än 0.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  private int _hp = 100;

  public void SetHp(int hp)
  {
    _hp = Math.Max(hp, 0);
  }
  
  public int GetHp()
  {
    return _hp;
  }
}
```

{% endcode %}

## Properties

Properties, även kallade **egenskaper**, fungerar som ett slags variabler med inbyggda getters och setters.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  private int _hp = 100;

  public int Hitpoints {
    get
    {
      return _hp;
    }
    set
    {
      _hp = Math.Max(value, 0);
    }
  }
}
```

{% endcode %}

Fördelen med att använda properties är att de kan anropas och användas som om de vore variabler:

{% code title="Program.cs" lineNumbers="true" %}

```csharp
Character cha = new Character();

// Propertyns setter anropas automatiskt, och value sätts till 80.
cha.Hitpoints = 80; 

// Propertyns getter anropas automatiskt, 
// och returnerar värdet av den privata variabeln hp.
Console.WriteLine(cha.Hitpoints);
```

{% endcode %}

### [Lambda](/grundlaggande/delegates#lambdas)-properties

Om det man vill göra med sin set resp. get är ganska enkelt, så behövs ingen fullständig kodblocks-syntax. Då kan man istället använda enkla lambdas:

```csharp
public class Character
{
  private int _hp = 100;

  public int Hitpoints
  {
    get => _hp;
    set => _hp = Math.Max(value, 0);
  }
}
```

### Properties som bara skickar vidare något (läsas, inte skrivas)

Om man inte ens behöver en set så kan hela propertien göras om till en lambda (den får då ingen set, utan bara en get):

```csharp
class Hero: Character
{
  int _xp = 0;
  
  public int Level => 1 + _xp / 10;
}
```

## Auto-implementerade properties

Om man inte vill lägga in någon extra logik alls i en property så kan man deklarera den på följande vis:

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  public int Hitpoints{ get; set; }
}
```

{% endcode %}

Det här innebär att man blir av med den fördel properties ger jämfört med publika variabler, men å andra sidan blir det lätt att senare bygga ut propertyn till en fullvärdig sådan. På det här viset behöver man med andra ord inte i efterhand byta ut en publik variabel mot en property när man senare kommer på att man trots allt ville ha lite logik.

### Properties med värden som bara får läsas, inte skrivas

Ett användningsområde för automatiskt implementerade properties är s.k. read only-värden. Säg t.ex. att vi vill att karaktärens hitpoints ska kunna läsas, men inte ändras, utifrån. Då skriver man så här:

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  public int Hitpoints{ get; private set; }
}
```

{% endcode %}

Det innebär att propertyns setter bara kan anropas från andra av klassens metoder.


# Static

Statiska variabler och metoder tillhör klassen istället för instanserna. Alla instanser delar alltså på en och samma variabel/metod.

## Statiska variabler

När man läser eller ändrar på en statisk variabel utifrån skriver man klassens namn, sedan en punkt och därefter variabelns namn. Inuti klassmetoder kan man alltid bara använda variabeln som vilken som helst.

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  // En statisk slumpgenerator som alla fighters delar på
  static Random _generator = new Random();
  
  private int _strength;
  
  // En konstruktor där slumpgeneratorn används
  public Fighter()
  {
    _strength = _generator.Next(10,20);
  }
}
```

{% endcode %}

## Statiska metoder

När man anropar en statisk metod skriver man klassens namn, sedan en punkt och därefter metodens namn. Inuti icke-statiska klassmetoder kan man anropa statiska metoder som om de vore vanliga metoder.

{% hint style="info" %}
En viktig detalj är att **inuti en statisk metod** kan man **bara** anropa de metoder i samma klass som **också är statiska**. Detta eftersom metoden tillhör just klassen och inte instanserna. Detta gäller också variabler - i en statisk metod kan man bara använda statiska klassvariabler.
{% endhint %}

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  public static string GetRandomFighterName()
  {
    /* ... */
  }
}
```

{% endcode %}


# Polymorfism \[…]

Se också [Virtual och Override](/klasser-och-objektorientering/polymorfism/virtual-override).

Polymorfism inom programmering är när flera olika saker liknar varandra så pass mycket att de kan ersätta varandra, eller när man kan använda ett och samma namn för att referera till flera olika saker.

Ett exempel på detta är [metodöverlagring](/grundlaggande/metoder#overlagring), där man använder samma namn på flera olika metoder, och C# använder parametervärden för att avgöra vilken metod som ska köras.

## Polymorfism, klasser och arv

Inom objektorientering används polymorfism genom att en variabel vars datatyp är satt till en basklass kan innehålla instanser av subklasser till den basklassen.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  public string Name {get; set;}
  public int Hp {get; set;} = 100;
  
  public void Hurt(int amount)
  {
    hp -= amount;
  }
}
```

{% endcode %}

{% code title="Hero.cs" lineNumbers="true" %}

```csharp
class Hero: Character
{
  int xp {get; private set;} = 0;
  int Level {get; private set;} = 1;
  
  public void AddExperience(int amount)
  {
    Xp += amount;
    Level = 1 + xp / 10;
  }
}
```

{% endcode %}

{% code title="Program.cs" lineNumbers="true" %}

```csharp
Character myHero = new Hero();
```

{% endcode %}

Det här är praktiskt när man till exempel vill ha en lista med alla karaktärer i spelet:

{% code title="Program.cs" lineNumbers="true" %}

```csharp
List<Character> characters = new List<Character>();

characters.Add(new Hero());
```

{% endcode %}

Ett problem med detta är att man då bara har tillgång till de publika variabler och metoder som ingår i basklassen. I exemplet ovan kan man med andra ord anropa `myHero.Hurt` eller `characters[0].Hurt` men man kan inte anropa `AddExperience` eftersom den bara finns i subklassen.

Därför är det en bra idé att tillföra så få nya metoder som behöver anropas utifrån som möjligt, när man designar subklasser som ska kunna fungera polymorfiskt. I idealfallet ingår alltså alla metoder och variabler som ska vara åtkomliga utifrån redan i basklassen.

## Tvingad tolkning

[As](/grundlaggande/typkonvertering#as) och framför allt [Is](/grundlaggande/typkonvertering#is) ger praktiska verktyg att arbeta med polymorfa klasser. Det är användbart framför allt när subklasser till exempel lägger till nya metoder eller properties.

{% code lineNumbers="true" %}

```csharp
foreach(Character c in characters)
{
  if (c is Hero h)
  {
    h.AddExperience(10);
  }
}
```

{% endcode %}


# Virtual, override

När man vill kunna låta en subklass ha en egen version av en metod som finns i basklassen så använder man virtual och override.

Virtual används för att markera metoder i basklassen som får "skrivas över" av subklasserna.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  protected int _hp = 100;
  protected int _damage = 5;
  
  public int Attack()
  {
    return Random.Shared.Next(_damage);
  }

  public virtual void Hurt(int amount)
  {
    _hp -= amount;
  }
}
```

{% endcode %}

Override används för att ge en subklass en egen version av en metod från basklassen som markerats som virtuell.

{% code title="Berbarian.cs" lineNumbers="true" %}

```csharp
class Barbarian: Character
{
  public override void Hurt(int amount)
  {
    _hp -= amount / 2;
  }
}
```

{% endcode %}

För att Override ska fungera så måste det finnas en metod i basklassen som ser likadan ut (samma namn, samma returtyp, samma antal parametrar med samma datatyper) och som är virtual.

Syftet med detta är att göra så att man inte måste skapa nya metoder åt subklasserna när de ska fungera annorlunda än basklassen. Det här är en av byggstenarna för [polymorfism](https://sites.google.com/view/csharp-referens/klasser-och-objektorientering/polymorfism?authuser=0).

### Base <a href="#h.p_gkwodfcvlsmn" id="h.p_gkwodfcvlsmn"></a>

Base låter en subklass få tillgång till basklassens version av en metod.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character
{
  protected int _hp = 100;
  protected int _damage = 5;

  public virtual int Attack()
  {
    return Random.Shared.Next(_damage);
  }

  public virtual void Hurt(int amount)
  {
    _hp -= amount;
  }
}
```

{% endcode %}

{% code title="Fighter.cs" lineNumbers="true" %}

```csharp
class Fighter
{
  public override int Attack()
  {
    return base.Attack() * 2;
  }
}
```

{% endcode %}

När en Fighter-instans' Attack-metod anropas i koden ovan, så anropas först basklassens Attack-metod, som returnerar 5. Den femman multipliceras med 2 och resultatet returneras. Med andra ord:

{% code lineNumbers="true" %}

```csharp
Fighter f = new Fighter();
int damage = f.Attack();
```

{% endcode %}

I exemplet ovan blir damage lika med 10.


# Generiska klasser

En generisk klass är en klass där någon datatyp inte är fördefinierad, utan deklareras i koden. En lista där värdena som lagras är `int` har till exempel datatypen List\<int> och en lista med strings är en List\<string>.

Det som skrivs mellan <> i en generisk klass kallas för en **typ-parameter**.

## Samlingar

C# innehåller ett antal färdiga generiska klasser i form av "samlingar" – helt enkelt objekt som *samlar* flera objekt eller värden av andra datatyper. Till exempel kan en samling innehålla integers, strings eller instanser av en klass.

Några exempel på generiska samlingar är [List](#list), [Queue](#queue), [PriorityQueue](#priorityqueue), [Stack](#stack), [HashSet ](#hashset)och [Dictionary](#dictionary).

{% hint style="info" %}
**OBS:** För att dessa ska fungera om du kör äldre versioner av dotnet (t.ex. dotnet 5), så behöver du skriva in följande högst upp i din kod:

```csharp
using System.Collections.Generic;
```

{% endhint %}

### Gemensamt för samlingar

Nedanstående finns i de flesta samlingar – några saknas i Dictionary, som är lite av ett specialfall.

Många samlings-datatyper kan också få ytterligare funktionalitet via [Linq-metoder](/annat/linq/linq-metoder).

#### Count

En [property ](/klasser-och-objektorientering/inkapsling-och-properties#properties)som används istället för Length för att räkna antalet saker i samlingen.

```csharp
List<int> myList = [1, 2, 3, 4, 5];

Console.WriteLine(myList.Count);
```

#### ToList() / ToArray()

Returnerar en lista eller en array som innehåller samma saker som samlingen.

```csharp
Queue<int> myQueue = new Queue<int>();
myQueue.Enqueue(4);

List<int> myList = myQueue.ToList();
```

#### Contains()

Tar emot ett värde. Om värdet finns i samlingen returnerar metoden true, annars false.

```csharp
List<int> myList = [4, 5, 6, 7];

if (myList.Contains(6))
{
  Console.WriteLine("Yes!");
}
```

#### Clear()

Rensar bort alla saker som finns i samlingen.

```csharp
List<int> myList = [4, 5, 6, 7];

myList.Clear();

Console.WriteLine(myList.Count); // skriver ut 0
```

### List

Fungerar som arrayer, utom att man inte bestämmer storlek från början utan kan använda bl.a Add och Insert och RemoveAt-metoder för att lägga till, stoppa in och ta bort grejer ur listan när som helst.

{% code lineNumbers="true" %}

```csharp
List<string> myList = [];

myList.Add("hej");

Console.WriteLine(myList[0])

List.RemoveAt(0);
```

{% endcode %}

När man skapar en lista kan man också direkt lägga in värden genom att ange en array efter parenteserna.

```csharp
List<int> myList = [1, 2, 3, 4, 5];
```

#### Add()

Lägger till något i listan.

```
myList.Add("hej");
```

#### Remove()

Tar bort något från listan. När man tar bort något ur listan

```
myList.Remove("hej");
```

#### RemoveAt()

Tar bort något från en specifik indexposition i listan.

```
myList.RemoveAt(0);
```

#### RemoveAll()

Tar emot en [delegate ](/grundlaggande/delegates)som beskriver ett kriterie. Delegaten tar emot ett objekt eller ett värde av samma datatyp som listan lagrar, och returnerar en bool ifall instansen uppfyller kriteriet. Normalt används ett [lambda-uttryck](/grundlaggande/delegates#lambdas) istället för en metod för att uppfylla delegaten.

RemoveAll() tar bort alla element som matchar kriteriet, och returnerar ett int-värde som beskriver hur många som togs bort.

```csharp
List<int> intList = [1, 2, 3, 4, 5];

int i = intList.RemoveAll(x => x > 3); // i blir 2, och 4 och 5 tas bort ur listan.
```

#### Find()

Tar emot en [delegate ](/grundlaggande/delegates)som beskriver ett kriterie. Delegaten tar emot ett objekt eller ett värde av samma datatyp som listan lagrar, och returnerar en bool ifall instansen uppfyller kriteriet. Normalt används ett [lambda-uttryck](/grundlaggande/delegates#lambdas) istället för en metod för att uppfylla delegaten.

Find() returnerar det första föremål (värde eller objekt) i listan som matchar kriteriet. Om inget hittas, returneras null eller defaultvärdet för datatypen (t.ex. 0 för integers).

```csharp
List<int> intList = [1, 2, 3, 4, 5];

int i = intList.Find(x => x > 3); // i blir 4
```

#### FindLast()

Fungerar som Find, men kollar igenom listan bakifrån och returnerar därmed det *sista* föremål som matchar kriteriet.

```csharp
List<int> intList = [1, 2, 3, 4, 5];

int i = intList.FindLast (x => x < 3); // i blir 2
```

#### FindAll()

Fungerar som Find, men returnerar en lista med *alla* matchande föremål i listan.

```csharp
List<int> intList = [1, 2, 3, 4, 5];

List<int> lowNumbers = intList.FindAll (x => x < 4); // lowNumbers blir 1,2,3
```

#### FindIndex()

Fungerar som Find, men returnerar *index* för första matchande föremål.

```csharp
List<int> intList = [11, 12, 13, 14, 15];

int i = intList.FindIndex (x => x > 12); // i blir 2
```

#### FindLastIndex()

Fungerar som FindIndex(), men kollar igenom listan bakifrån och returnerar därmed *index* för det *sista* föremål som matchar kriteriet.

```csharp
List<int> intList = [11, 12, 13, 14, 15];

int i = intList.FindLastIndex (x => x < 13); // i blir 1
```

### Queue

Fungerar som en lista, utom att man bara kan lägga till saker längst bak i kön, och ta bort dem längst fram. Detta kallas FIFO, eller First In, First Out.

{% code lineNumbers="true" %}

```csharp
Queue<int> myQueue = new Queue<int>();

myQueue.Enqueue(5);
myQueue.Enqueue(42);
myQueue.Enqueue(665);

// Peek returnerar en kopia av värdet som ligger 
// längst fram i kön – 5 i det här fallet
Console.WriteLine(myQueue.Peek());

// Dequeue tar bort värdet som ligger längst fram ur kön 
// och returnerar det. Så nu är kön = 42, 665.
int n = myQueue.Dequeue();
```

{% endcode %}

#### Enqueue()

Lägger till ett objekt i kön.

```csharp
myQueue.Enqueue(5);
```

#### Dequeue()

Tar bort och returnerar nästa objekt i kön.

```csharp
int n = myQueue.Dequeue();
```

#### Peek()

Returnerar, men tar inte bort, nästa objekt i kön.

```csharp
Console.WriteLine(myQueue.Peek();
```

### PriorityQueue

Fungerar som en Queue, plus att varje sak som läggs in i kön ges en *prioritet*. När man sedan kör Dequeue eller Peek så är det objektet med högst prioritet (lägst prioritets-värde) som returneras. När man skapar en PriorityQueue så anger man två datatyper – en för de saker som ska sparas i kön, en som ska användas för att avgöra prioritet. Oftast är den senare bara en int eller annan numerisk datatyp.

Om flera saker har samma prioritet så returneras de i ordning motsvarande en vanlig queue.

```csharp
PriorityQueue<string, int> queue = new PriorityQueue<string, int>();

queue.Enqueue("Micke", 2);
queue.Enqueue("Martin", 1);
queue.Enqueue("Lena", 3);

Console.WriteLine(queue.Peek()); // Skriver ut "Martin"
```

### Stack

Fungerar som en "hög" – man kan bara lägga till saker högst upp i högen och även bara plocka bort saker från högst upp i högen. Detta kallas FILO, eller First In, Last Out.

{% code lineNumbers="true" %}

```csharp
Stack<int> myStack = new Stack<int>();

myStack.Push(5);
myStack.Push(42);
myStack.Push(665);

// Precis som för queue, peekar "nästa värde". Det som ligger högst upp – 665.
Console.WriteLine(myStack.Peek());

// Tar bort det som ligger högst upp i högen och returnerar det.
// Så nu är bara 5 och 42 kvar i högen.
int n = myStack.Pop();
```

{% endcode %}

### HashSet

Saknar indexering, men kan bara innehålla unika objekt – man riskerar inte att råka lägga till samma sak flera gånger.

{% code lineNumbers="true" %}

```csharp
HashSet<int> mySet = new HashSet<int>();

mySet.Add(5);
mySet.Add(42);
mySet.Add(5);

// skriver ut true, eftersom 5 ingår i setet.
Console.WriteLine(mySet.Contains(5));

// Skriver ut 2, för det finns bara 2 unika objekt i setet
//  – den andra femman lades aldrig till.
Console.WriteLine(mySet.Count());
```

{% endcode %}

### Dictionary

Fungerar som en lista, utom att man kan använda andra datatyper än ints som index. I Dictionaries använder man ofta ordet "key" istället för "index".

{% code lineNumbers="true" %}

```csharp
Dictionary<string, int> myStats = new Dictionary<string, int>();

myStats.Add("Strength", 20);
myStats.Add("Intelligence", 12);

Console.WriteLine(myStats["Strength"]);
```

{% endcode %}

#### Keys

Man kan få fram en samling av alla keys i ett dictionary genom att läsa av egenskapen Keys som är inbyggd i alla Dictionaries.

{% code lineNumbers="true" %}

```csharp
foreach (string key in myStats.Keys)
{
  Console.WriteLine($"{key}: {myStats[key]}");
}
```

{% endcode %}

## Skapa egna generiska klasser

Generiska klasser är oftast "container-klasser", alltså klasser vars uppgift det är att lagra ett annat värde.

{% code title="Node.cs" lineNumbers="true" %}

```csharp
class Node<T>
{
  public T Value;
  public Node NextNode;
}
```

{% endcode %}

Ovanstående kod är en enkel nod i en s.k. länkad lista. I en länkad lista känner varje nod bara till "nästa nod".

Nu bestäms vilken datatyp variabeln value ska ha genom att den anges mellan <> när instansen skapas:

{% code lineNumbers="true" %}

```csharp
Node<string> firstTextNode = new Node<string>(); // value blir en string
firstTextNode.Value = "Bananas";

Node<int> firstNumberNode = new Node<int>(); // value blir en int
firstNumberNode.Value = 23;
```

{% endcode %}


# Abstract

## Abstrakta klasser

En abstrakt klass kan aldrig instansieras, utan kan bara användas som basklass för arv.

{% code title="Character.cs" lineNumbers="true" %}

```csharp
abstract class Character
{
  public string Name;
  public int Hp = 100;

  public void Hurt(int amount)
  {
    Hp -= amount;
  }
}
```

{% endcode %}

{% code title="Hero.cs" lineNumbers="true" %}

```csharp
class Hero: Character
{
  int _xp = 0;
  int _level = 1;
  public void AddExperience(int amount)
  {
    _xp += amount;
    _level = 1 + _xp / 10;
  }
}
```

{% endcode %}

## Abstrakta metoder

Den huvudsakliga anledningen till att göra en basklass abstrakt är för att man vill kunna använda sig av abstrakta metoder. En abstrakt metod saknar kod, och måste overridas i alla subklasser. Det är med andra ord ett sätt att tvinga de som skapar subklasser att bygga egna versioner av den metoden.

Abstrakta metoder fungerar bäst i de fall där det inte finns någon lämplig "standardversion" av metoden som kan ingå i basklassen

{% code title="Character.cs" lineNumbers="true" %}

```csharp
abstract class Character
{
  public string Name;
  public int Hp = 100;
  public int Strength = 5;
  public int Level = 1;
  public int Xp = 0;
  public string[] Attacks = {"Kick", "Punch"}

  public abstract void LevelUp();
}
```

{% endcode %}

{% code title="Warrior.cs" lineNumbers="true" %}

```csharp
class Warrior : Character
{
  public override void LevelUp()
  {
    Level = Xp / 10;
    if (Level == 3)
    {
      Attacks = new string[] { "Kick", "Punch", "Bite" };
    }
  }
}
```

{% endcode %}

I exemplet ovan är det alltså tänkt att metoden LevelUp ska anropas för att ge karaktärer ny level, ifall de fått tillräckligt med xp. I och med att olika karaktärer ska ha olika progression baserat på vilken klass de tillhör (t.ex. Warrior) så kan man låta LevelUp-metoden vara abstrakt och ha en egen implementation för varje subklass.


# Interface

Ett interface är ett slags kravspecifikation som beskriver ett antal metoder som en klass behöver implementera. De fungerar som ett slags tvingande abstrakta klasser. När en klass "ärver" från ett interface så kallas det att klassen implementerar interfacet.

Interfaces namnges med PascalCase och med ett I (stora i) i början.

{% code title="IDamagable.cs" lineNumbers="true" %}

```csharp
interface IDamagable
{
  void Hurt(int amount);
}
```

{% endcode %}

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character : IDamagable
{
  public string Name;
  public int Hp = 100;

  public void Hurt(int amount)
  {
    Hp -= amount;
  }
}
```

{% endcode %}

Interfacet Damagable specificerar att klasser som implementerar det måste ha en Hurt-metod.

Sedan kan man designa t.ex. metoder som kan ta emot vilken klass sim helst som implemeterar interfacet som parameter:

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character : IDamagable
{
  public string Name;
  public int Hp = 100;

  public void Hurt(int amount)
  {
     Hp -= amount;
  }

  public void Attack(IDamagable target)
  {
    target.Hurt(5);
  }
}
```

{% endcode %}

I exemplet ovan kan man alltså stoppa in Characters - eller vad som helst som implementerar Damagable - i metoden Attack. Eftersom man vet att alla klasser som implementerar Damagable har en Hurt-metod.

Sedan behöver den som designar andra saker i spelet som kan skadas - väggar, växter, utrustning, känslor - bara se till att hens klasser implementerar Damagable, så vet man att klasserna kommer att fungera tillsammans med karaktärernas Attack-metod.

## Implementera flera interfaces

En och samma klass kan implementera flera interfaces.

{% code title="IDamagable.cs" lineNumbers="true" %}

```csharp
interface IDamagable
{
  void Hurt(int amount);
}
```

{% endcode %}

{% code title="IAttacking.cs" lineNumbers="true" %}

```csharp
interface IAttacking
{
  void Attack(Damagable target);
}
```

{% endcode %}

{% code title="Character.cs" lineNumbers="true" %}

```csharp
class Character : IDamagable, IAttacking
{
  public string Name;
  public int Hp = 100;

  public void Hurt(int amount)
  {
     Hp -= amount;
  }

  public void Attack(Damagable target)
  {
    target.Hurt(5);
  }
}
```

{% endcode %}

Eftersom interfaces mer fungerar som kravspecifikationer än traditionella arv så innebär detta med andra ord helt enkelt att klassen uppfyller de krav som ställs upp av både IDamagable och IAttacking.


# Attribut

Attribut används för att säga saker *om* klassvariabler, properties och metoder. Med andra ord är de ett slags *metadata* – information om information.

De används en hel del när man konstruerar controllers till REST-servrar, och när man jobbar med JSON-serialisering.

Man skriver attribut mellan hakparenteser `[]` innan det attributet ska gälla.

{% code title="Pokemon.cs" lineNumbers="true" %}

```csharp
using System.Text.Json.Serialization;

public class Pokemon
{
  public string Name {get; set;}
  public bool IsDefault {get; set;}
  
  [JsonIgnore]
  public int CurrentHp {get; set;}
}
```

{% endcode %}


# RayLib \[…]

RayLib är ett grafikbibliotek som är ganska lätt att komma igång med och som påminner om traditionella bibliotek som t.ex. SDL.

I vanliga fall är RayLib, som de flesta bibliotek, gjort för C++. Men det går ganska lätt att använda till C# också.

Den officiella dokumentationen består dels av [en lathund](https://www.raylib.com/cheatsheet/cheatsheet.html), dels av en ganska [välfylld wiki](https://github.com/raysan5/raylib/wiki). Däremot är båda 100% anpassade för C++ och inte C#, vilket gör att man det är en del skillnader.

Innehåll:

* [Raylib setup](/annat/raylib/raylib-setup)
* [Fönster i Raylib](/annat/raylib/foenster-i-raylib)
* [Grundläggande grafik](/annat/raylib/grafik)
* [Geometriska former](/annat/raylib/geometriska-former)
* [Bilder och texturer](/annat/raylib/bilder-och-texturer)
* [Input](/annat/raylib/input)
* [Text](/annat/raylib/text)
* [Rectangle](/annat/raylib/rectangle)
* [Kollisioner](/annat/raylib/kollisioner)
* [Kamera](/annat/raylib/kamera)
* [Ljud](/annat/raylib/ljud)


# Raylib setup

Skapa ett nytt konsollprojekt som vanligt.

* Ta fram **NuGet-fliken** i Visual Studio Codes nedre panel (bredvid Terminal). Du behöver [ha tillägget NuGet Gallery installerat](https://marketplace.visualstudio.com/items?itemName=patcx.vscode-nuget-gallery).
  * Om du inte ser den fliken, tryck F1 och sök efter "nuget", välj "Focus on NuGet view".
* I galleriet, sök efter Raylib. Välj senaste versionen av "Raylib\_cs".
* Kryssa i ditt projekt, klicka Install.
* Om du vill använda bilder eller andra filer i ditt spel, se till att [konfigurera din csproj för att hantera resursfiler](/filhantering/resursfiler#losning-1-kopiera-filerna-automatiskt-till-malmappen).

### Inkludera Raylib <a href="#h.p_juwpvkt-mpln" id="h.p_juwpvkt-mpln"></a>

{% hint style="warning" %}
**OBSERVERA:** För att du ska kunna använda Raylib så måste du skriva in följande bland dina using-rader högst upp i programfilen:

```csharp
using Raylib_cs;
```

{% endhint %}


# Fönster i Raylib

## Skapa fönster

Att skapa ett nytt fönster för Raylib görs med en enkel kodrad:

```csharp
Raylib.InitWindow(800, 600, "Hello World");
```

800 är fönstrets bredd, 600 dess höjd, och "Hello World" är vad som kommer att stå i titeln.

## WindowShouldClose()

Returnerar False så länge användaren inte skickat signalen att fönstret borde stängas – till exempel genom att trycka på krysset.

Ett vanligt sätt att bygga spelets grund-loop är att använda denna ihop med en while-loop:

```csharp
while (!Raylib.WindowShouldClose())
{
  // Spelets logik
}
```

## Ett enkelt komplett exempel

I exemplet nedan initieras Raylib-fönstret. Sedan körs en loop så länge fönstret är öppet, och varje bildruta ritas först en vit bakgrund och sedan en magentafärgad cirkel.

```csharp
using Raylib_cs;

Raylib.InitWindow(800, 600, "The title of my window");
Raylib.SetTargetFPS(60);

while (!Raylib.WindowShouldClose())
{
  Raylib.BeginDrawing();
  
  Raylib.ClearBackground(Color.WHITE);
  
  Raylib.DrawCircle(100,100,100,Color.MAGENTA);
  
  Raylib.EndDrawing();
}
```

## Snippet

Här är koden för en [snippet ](/mjukvara/visual-studio-code/snippets)som skapar grundkoden för Raylib:

```json
"Raylib-boilerplate": {
  "prefix": "rayl",
  "body": [
    "using Raylib_cs;\n",
    "Raylib.InitWindow(${1:800}, ${2:600}, \"${3:Title}\");",
    "Raylib.SetTargetFPS(60);\n",
    "while (!Raylib.WindowShouldClose())",
    "{",
    "  $0\n",
    "  Raylib.BeginDrawing();",
    "  Raylib.ClearBackground(Color.WHITE);",
    "  Raylib.EndDrawing();",
    "}"
  ]
},
```


# Grundläggande grafik

## Mått och koordinatsystem

Observera att koordinatsystemet i Raylib har **origo i övre vänstra hörnet**, och att **Y-axeln är omvänd** så att positiva värden går nedåt.

Måtten är i **pixlar**.

## SetTargetFps()

Används normalt utanför spel-loopen, för att begränsa antalet bildrutor per sekund. Är ett av de sätt som finns att få t.ex. förflyttningar att ske lika snabbt på alla datorer.

```csharp
Raylib.SetTargetFps(60); // Begränsar till 60fps
```

## BeginDrawing(), EndDrawing()

Används för att påbörja, respektive avsluta, den delen av spelloopen som ritar ut saker till fönstret.

```csharp
while (!Raylib.WindowShouldClose())
{
  // Spelets logik
  
  Raylib.BeginDrawing();
  
  // Kod för att rita ut saker till fönstret
  
  Raylib.EndDrawing();
}
```

## ClearBackground()

Rensar fönstret. Görs normalt kort efter BeginDrawing.

```csharp
while (!Raylib.WindowShouldClose())
{
  Raylib.BeginDrawing();

  Raylib.ClearBackground(Color.WHITE);
  
  Raylib.EndDrawing();
}
```

## Färger

Det finns en hel del färdiga färger i Raylib, till exempel Color.MAGENTA eller Color.ORANGE.

Om man vill skapa en egen ny färg så kan man göra det:

```csharp
Color hotPink = new Color(255, 105, 180, 255);
```

Parametrarna är helt enkelt siffror från 0–255 för rött, grönt, blått och alpha (genomskinlighet). 0 alpha är helt genomskinlig, 255 är helt ogenomskinlig.


# Geometriska former

## Rektanglar

### DrawRectangle()

```csharp
Raylib.DrawRectangle(10, 10, 30, 40, Color.ORANGE);
```

Parametrarna är, i tur och ordning: X- och Y-position för rektangelns övre vänstra hörn, rektangelns bredd och höjd, och dess färg.

### DrawRectangleLines(), DrawCircleLines()

Fungerar precis som DrawCircle respektive DrawRectangle, men använder färgen för att rita ut respektive forms kanter istället för att fylla dem.

```csharp
Raylib.DrawCircleLines(150, 200, 40, Color.MAGENTA);
```

### DrawRectangleRec()

Fungerar precis som DrawRectangle, men tar emot ett [Rectangle](/annat/raylib/rectangle)-objekt istället för koordinater och bredd/höjd.

```csharp
Rectangle r1 = new Rectangle(10,5,30,15);
Raylib.DrawRectangleRec(r1, Color.PINK);
```

## Cirklar och elipser

### DrawCircle()

```csharp
Raylib.DrawCircle(150, 200, 40, Color.MAGENTA);
```

Parametrarna är, i tur och ordning: X- och Y-position för cirkelns mitt, cirkelns radie, och cirkelns färg.

### DrawCircleV()

Ritar en cirkel men använder en [Vector2 ](/grundlaggande/vektorer-numerics#vector2)som mittpunkt.

```csharp
Vector2 midPoint = new Vector2(100, 100);
Raylib.DrawCircleV(midPoint, 40, Color.PINK);
```

### DrawCircleSector()

Ritar en del av en cirkel.

```csharp
Vector2 midPoint = new Vector2(100, 100);
Raylib.DrawCircleSector(midPoint, 50, 0, -45, 100, Color.PINK);
```

Parametrarna är alltså mittpunkten, radien, startgraden, slutgraden, antalet segment som ska ritas ut samt färgen. Graderna utgår från att noll är rakt nedåt, och räknar motsols(!). Med andra ord är 0 nedåt, 90 är rakt åt höger och −90 är rakt åt vänster.

### DrawEllipse()

Ritar ut en ellips. Parametrarna är mittpunktens x- och y-värde, den horisontella radien och den vertikala radien.

```csharp
Raylib.DrawEllipse(100, 250, 50, 200, Color.PINK);
```

## Andra former

### DrawTriangle()

Ritar ut en triangel. Parametrarna är triangelns tre hörn som [Vector2](/grundlaggande/vektorer-numerics#vector2) samt den färg triangeln ska ha.

```csharp
Vector2 top = new Vector2(150, 100);
Vector2 bottomLeft = new Vector2(100, 150);
Vector2 bottomRight = new Vector2(200, 150);

Raylib.DrawTriangle(top, bottomLeft, bottomRight, Color.GRAY);
```

{% hint style="info" %}
**OBSERVERA:** Ange vektorerna i *motsols ordning*.
{% endhint %}

### DrawPoly()

Ritar en polygon. Parametrarna är mittpunkten, antalet sidor, radien, rotationen och färgen.

```csharp
Raylib.DrawPoly(centerPoint, 7, 64, 0, Color.GREEN);
```

## Linjer

### DrawLine()

Ritar en linje mellan två punkter. Parametrarna är startpunktens x- och y-värden och slutpunktens x- och y-värde, samt färgen.

```csharp
Raylib.DrawLine(10, 10, 10, 20, Color.PINK);
```

### DrawLineV()

Ritar en linje mellan två punkter. Parametrarna är en [vektor2 ](/grundlaggande/vektorer-numerics#vector2)för startpunkten, en vektor2 för slutpunkten, samt färgen.

```csharp
  Vector2 start = new Vector2(10,10);
  Vector2 end = new Vector2(10,20);

  Raylib.DrawLineV(start, end, Color.RED);
```

### DrawLineEx()

Precis som DrawLineV fast med en extra parameter: tjockleken.

```csharp
Raylib.DrawLineEx(start, end, 10, Color.GREEN);
```

### DrawLineBezierQuad()

Rita en böjd linje. Funkar som DrawLineEx, men med en extra parameter: en punkt som linjen böjer sig mot.

```csharp
  Vector2 start = new Vector2(10,10);
  Vector2 end = new Vector2(100,100);
  Vector2 control = new Vector2(200, 10);

  Raylib.DrawLineBezierQuad(start, end, control, 5, Color.GREEN);
```


# Bilder och texturer

## Bilder och texturer

I Raylib skiljer man på *Images* och *Textures*.

Skillnaden är att Images kan *redigeras*. Textures kan *ritas ut till skärmen*.

### Filformat som stöds

* png
* bmp
* tga
* gif (dock ej animationer)
* dds, hdr, ktx, astc

{% hint style="info" %}
**Observera** att det saknas stöd för jpg – detta eftersom jpg är väldigt ovanligt i spel.
{% endhint %}

{% hint style="info" %}
**Observera** att alla bilder är [**resursfiler**](/filhantering/resursfiler). Det betyder att du måste[ krångla lite](/filhantering/resursfiler#losning-1-kopiera-filerna-automatiskt-till-malmappen) för att vara säker på att programmet kan hitta dem.&#x20;
{% endhint %}

## [Texture](/annat/raylib/bilder-och-texturer/texture)

En Texture är en bild som är sparad i grafikkortets minne (VRAM), och är redo att ritas ut på skärmen. Man kan skapa en Texture utifrån en [Image ](#image)eller läsa in en bildfil från hårddisken direkt.

## [Image](/annat/raylib/bilder-och-texturer/image)

En Image är en bild som är sparad i datorns arbetsminne (RAM), och kan redigeras på olika sätt.

För att man ska kunna rita ut den till fönstret behöver man sedan konvertera den till en [texture](#texture). Det gör man genom [LoadTextureFromImage](/annat/raylib/bilder-och-texturer/texture#loadtexturefromimage).


# Texture

En Texture är en bild som är sparad i grafikkortets minne, och är redo att ritas ut på skärmen. Man kan skapa en Texture utifrån en [Image ](/annat/raylib/bilder-och-texturer/image)eller läsa in en bildfil från hårddisken direkt.

## Width och height

Varje texture har en width och en height.

```csharp
Console.WriteLine($"Width: {goombaTexture.Width});
Console.WriteLine($"Height: {goombaTexture.Height});

Rectangle hitBox = new Rectangle(0, 0, goombaTexture.Width, goombaTexture.Height);
```

## Läsa in

### LoadTexture()

Läser in en bildfil och skapar en texture direkt från den.

```csharp
Texture2D goombaTexture = Raylib.LoadTexture(@"goomba.png");
```

### LoadTextureFromImage()

Skapar en ny texture baserat på en [Image](/annat/raylib/bilder-och-texturer/image).

```csharp
Texture2D heroTexture = Raylib.LoadTextureFromImage(originalImage);
```

Detta är alltså motsatsen till [LoadImageFromTexture()](/annat/raylib/bilder-och-texturer/image#loadimagefromtexture).

## Rita ut till skärmen

### DrawTexture()

Ritar ut en texture till fönstret.

```csharp
// Ritar texturen heroTexture till fönstret, på x-position 40 och 
// y-position 300, utan infärgning (WHITE färgar inte)
Raylib.DrawTexture(heroTexture, 40, 300, Color.WHITE)
```

### DrawTextureEx()

Ritar ut en texture till fönstret, med andra parametrar: En [Vector2 ](/grundlaggande/vektorer-numerics#vector2)för att ange x och y-positionen den ska ritas ut på, och floats som anger rotation och skalning av texturen.

Rotationen anges i grader och skalningen i decimalform.

```csharp
// Ritar texturen heroTexture till fönstret, på x-position 40 och 
// y-position 300, utan infärgning (WHITE färgar inte)
// Använd skalning 0.5 och rotation 0.
Vector2 position = new Vector2(40, 300);
Raylib.DrawTexture(heroTexture, position, 0, 0.5f, Color.WHITE)
```

{% hint style="info" %}
**OBSERVERA:** För att kunna använda [Vector2 ](/grundlaggande/vektorer-numerics)så måste du lägga in detta bland dina using-statements:

```csharp
using System.Numerics;
```

{% endhint %}

### DrawTextureRec()

Ritar ut en del av en texture till fönstret. Fungerar som DrawTextureEx men utan rotationen och skalan, och med en rektangel som säger vilken del av texturen man vill klippa ut.

```csharp
Rectangle source = new Rectangle(0, 0, 100, 100);
Vector2 position = new Vector(40, 300);

Raylib.DrawTextureRec(heroTexture, source, position, Color.WHITE);
```

Det här kan man bland annat använda sig av när man har en bild som är ett s.k. sprite sheet, där alla bildrutor i en karaktärs animation finns med. Man behöver då inte klippa upp animationen i en massa olika bildfiler utan kan istället använda DrawTexturePro för att kopiera en del av bilden till raylibfönstret i taget.

Man kan också ange en source-rektangel med negativ bredd eller höjd för att få en urklippt bild som är flippad längs x- eller y-axeln.

```csharp
Rectangle source = new Rectangle(0, 0, -100, 100);
Vector2 position = new Vector(40, 300);

Raylib.DrawTextureRec(heroTexture, source, position, Color.WHITE);
```

### DrawTexturePro()

En ännu mer avancerad version av DrawTexture. Här anges två rektanglar – en för källan, alltså vilken del av texturen som ska kopieras. Och så en för destinationen, alltså var någonstans på fönstret kopian ska placeras och hur stor den ska göras.

Dessutom anges en Vector2 för "origin", som är den position som ritandet och roterandet utgår från. Vill man rotera och skala en textur kring dess mittpunkt anger man alltså en Vector2 vars x- och y-värden är halva destination-rektangelns bredd och höjd.

```csharp
Texture2D spriteSheet = Raylib.LoadTexture("herosheet.png");

// Det som ska kopieras från texturen är en ruta i storlek 64x64 pixlar från 
//  dess övre vänstra hörn (0,0)
Rectangle heroSpriteSource = new Rectangle(0,0,64,64);

// Hjältespriten ska ritas ut på position 200, 200 och förstoras upp till 256x256.
Rectangle heroSpriteDest = new Rectangle(200, 200, 256, 256);

// En Vector2 med halva destinationens bredd och höjd som x- och y-värde.
// Den räknas från destinationens övre vänstra hörn, så hamnar alltså i mitten av den.
Vector2 heroOrigin = new Vector2(
  heroSpriteDest.width / 2,
  heroSpriteDest.height / 2
);

float rotation = 0;

// ---

Raylib.DrawTexturePro(
  texture, 
  heroSpriteSource,
  heroSpriteDest,
  heroOrigin,
  rotation,
  Color.WHITE );
```

Bilden nedan visar principen:

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHmNgpRz-b16wpwGwZI%2F-MZC5AhyTqfxvz6TbqAT%2F-MZCFL-RA3XUqbybUWyM%2FDrawTexturePro.png?alt=media\&token=59b654d3-af9b-45f7-af0c-00e1e2d10d9c)

### SetTextureFilter()

I vanliga fall när man ritar ut en texture i en annan storlek än den är från början så skalas den med interpolering – den hittar på mjuka övergångar mellan originalpixlarna. Det fungerar bra för foton och liknande, men sämre för pixelart.

```csharp
// Bestäm att texturen heroTexture ska skalas med "point"-filter, som ger skarp
// pixelart - ingen interpolering.
Raylib.SetTextureFilter(heroTexture, TextureFilter.TEXTURE_FILTER_POINT);
```


# Image

En Image är en bild som är sparad i datorns arbetsminne, och kan manipuleras på olika sätt.

För att man ska kunna rita ut den till fönstret behöver man sedan konvertera den till en [texture](/annat/raylib/bilder-och-texturer/texture). Det gör man genom [LoadTextureFromImage](/annat/raylib/bilder-och-texturer/texture#loadtexturefromimage).

## Width och height

Varje image har en width och en height.

```csharp
Console.WriteLine($"Width: {filebasedImage.Width});
Console.WriteLine($"Height: {filebasedImage.Height});

Rectangle hitBox = new Rectangle(0, 0, filebasedImage.Width, filebasedimage.Height);
```

## Skapa eller ladda in

### LoadImage()

Läser in en bildfil från hårddisken och lagrar den i minnet som en Image.

**OBS!** bilden måste ligga i samma mapp som Program.cs-filen!

```csharp
Image filebasedImage = Raylib.LoadImage(@"hero.png");
```

### LoadImageFromTexture()

Läser in en bildfil från en textur och lagrar den i minnet som en Image.

```csharp
Image goombaImage = Raylib.LoadImageFromTexture(goombaTexture);
```

Detta är alltså motsatsen till [LoadTextureFromImage()](/annat/raylib/bilder-och-texturer/texture#loadtexturefromimage).

### LoadImageFromScreen()

Kopierar det som just nu syns i fönstret.

```csharp
Image screenshot = Raylib.LoadImageFromScree();
```

### GenImageColor()

Skapar en ny blank image i minnet, fylld av den angivna färgen.

```csharp
// Skapar en svart bild som är 200x200 pixlar.
Image blackImage = Raylib.GenImageColor(200, 200, Color.BLACK);

// Skapar en röd bild som är 200x200 pixlar.
Image redImage = Raylib.GenImageColor(200, 200, Color.RED);
```

## Redigera

De flesta metoder här använder nyckelordet [ref ](/grundlaggande/reference-vs-value-types#out-och-ref)för att ange att den bild man stoppar in som parameter inte returneras i förändrad form, utan ändras på plats i minnet.

### ImageDrawPixel()

Ändrar färg på en pixel i en Image.

```csharp
// Ändrar pixeln som är 20 pixlar från vänsterkanten och 15 från 
// toppen av bilden till att bli blå
Raylib.ImageDrawPixel(ref targetImage, 20, 15, Color.BLUE);
```

### ImageDrawCircle()

Fungerar som [DrawCircle()](/annat/raylib/geometriska-former#drawcircle).

```csharp
Raylib.ImageDrawCircle(ref targetImage, 150, 200, 40, Color.MAGENTA);
```

### ImageDrawRectangle()

Fungerar som [DrawRectangle()](/annat/raylib/geometriska-former#drawrectangle).

```csharp
Raylib.ImageDrawRectangle(ref targetImage, 10, 10, 30, 40, Color.ORANGE);
```

### ImageDrawRectangleRec()

Fungerar som [DrawRectangleRec()](/annat/raylib/geometriska-former#drawrectanglerec).

```csharp
Rectangle r1 = new Rectangle(10,5,30,15);
Raylib.ImageDrawRectangleRec(ref targetImage, r1, Color.PINK);
```

### ImageDrawText()

Fungerar som [DrawText()](/annat/raylib/text#drawtext).

```csharp
Raylib.ImageDrawText(ref targetImage, "Hello World", 100, 50, 20, Color.ORANGE);
```

### ImageDrawTextEx()

Fungerar som [DrawTextEx()](/annat/raylib/text#drawtextex).

```csharp
Raylib.DrawTextEx(ref targetImage, f1, "Hello", new Vector2(20, 15), 40,0,Color.BLACK);
```

### GetImageColor()

Läser av färgen på en specifik pixel.

```
// Hämtar färgen från x: 53, y: 17 i bilden redImage.
Color c = Raylib.GetImageColor(redImage, 53, 17);
```

### ImageFlipHorizontal()

Flippar en Image horisontellt (spegelvänder).

```csharp
Raylib.ImageFlipHorizontal(ref targetImage);
```

### ImageFlipVertical()

Flippar en Image vertikalt.

```csharp
Raylib.ImageFlipVertical(ref targetImage);
```

### ImageResize/ImageResizeNN()

Ändrar storlek på en bild. NN-versionen ger ett skarpt resultat vilket fungerar bra för pixelart som skalas med jämna multiplikationer.

```csharp
//Ändrar storleken på bilden "someImage" till 400x400 pixlar
Raylib.ImageResize(ref targetImage, 400, 400);

//Ändrar storleken på bilden "pixelartImage" till dubbla dess nuvarande storlek
RayLib.ImageResizeNN(ref pixelartImage, pixelartImage * 2, pixelartImage * 2);
```

## Spara till hårddisken

### ExportImage

Sparar en Image till hårddisken, som en png-bild.

```csharp
Raylib.ExportImage(sourceImage, "hello.png");
```

{% hint style="info" %}
**OBS:** Filnamnet *måste* sluta med ".png"!
{% endhint %}


# Input

## Tangentbordet

### IsKeyDown()

Tar emot en tangent som parameter; returnerar true om den angivna tangenten är nedtryckt – false om den inte är det.

Under KeyboardKey finns variabler för i princip alla tangenter på tangentbordet.

```csharp
if (Raylib.IsKeyDown(KeyboardKey.KEY_LEFT))
{
  // Kodlogik
}
```

### IsKeyUp()

Fungerar som IsKeyDown fast… tvärtom

```csharp
if (Raylib.IsKeyUp(KeyboardKey.KEY_LEFT))
{
  // Kodlogik
}
```

### IsKeyPressed()

Returnerar true om knappen tryckts ned denna frame.

```csharp
if (Raylib.IsKeyPressed(KeyboardKey.KEY_SPACE))
{
  Jump();
}
```

### IsKeyReleased()

Returnerar true om knappen släppts upp denna frame.

```csharp
  if (Raylib.IsKeyReleased(KeyboardKey.KEY_LEFT_CTRL))
  {
    FireShot(shotPower);
    shotPower = 0;
  }
```

### SetExitKey()

I vanliga fall innebär ett tryck på ESC-knappen att hela spelet avslutas. SetExitKey kan användas för att byta vilken knapp som har den funktionen – eller ta bort den helt.

```csharp
Raylib.SetExitKey(KeyboardKey.KEY_Q); // Gör så Q avslutar spelet

Raylib.SetExitKey(0); // Gör så att det inte finns någon "avsluta spelet-knapp".
```

## Musen

### GetMouseX, GetMouseY

Hämtar musens nuvarande position i form av integervärden i x- respektive y-led.

```csharp
int mouseX = Raylib.GetMouseX();
int mouseY = Raylib.GetMouseY();
```

### GetMousePosition()

Hämtar musens nuvarande position i form av en tvådimensionell [vektor](/grundlaggande/vektorer-numerics).

```csharp
Vector2 mousePos = Raylib.GetMousePosition();
```

### IsMouseButtonDown()

Anropas med en musknapp som parameter; returnerar true om den musknappen just nu är nedtryckt.

```csharp
bool leftDown = Raylib.IsMouseButtonDown(MouseButton.MOUSE_LEFT_BUTTON);
bool rightDown = Raylib.IsMouseButtonDown(MouseButton.MOUSE_RIGHT_BUTTON);
```

### IsMouseButtonPressed()

Anropas med en musknapp som parameter; returnerar true om den musknappen tryckts ned någon gång sedan förra gången metoden anropades.

```csharp
bool leftWasPressed = Raylib.IsMouseButtonPressed(MouseButton.MOUSE_LEFT_BUTTON);
```


# Text

## DrawText()

Ritar ut text.

```csharp
// Ritar ut texten "Hello World" på x-position 100 och y-position 50,
// med text i storlek 20 och med orange färg.
Raylib.DrawText("Hello World", 100, 50, 20, Color.ORANGE);
```

## LoadFont()

Laddar in en typsnittsfil (ttf eller otf-format)

```csharp
Font f1 = Raylib.LoadFont(@"Metrophobic.ttf");
```

{% hint style="info" %}
**OBSERVERA:** För att få å, ä och ö att fungera eller för att kunna använda typsnittet i en specifik storlek, använd LoadFontEx istället.
{% endhint %}

## LoadFontEx()

Laddar in en typsnittsfil (ttf eller otf-format) med extra parametrar

```csharp
// Ladda in typsnittsfilen Lato-Regular.ttf, i storleken 36.
//  Vi anger null eftersom vi inte vill ange exakt vilka tecken som ska laddas in.
//  Vi anger 256 eftersom vi vill ladda in de 256 första tecknen – vilket inkluderar åäö
Font f2 = Raylib.LoadFontEx(@"Lato-Regular.ttf", 36, null, 256);
```

## DrawTextEx()

Mer avancerad variant av DrawText, som använder Vector2 för positionering och tillåter att man anger typsnitt. Kräver att man lagt in `using System.Numerics;` högst upp.

```csharp
// Ritar ut texten "Hello" på x- position 20 och y-position 15,
// i storlek 40, utan något extra mellanrum mellan bokstäverna, med svart färg.
Raylib.DrawTextEx(f1, "Hello", new Vector2(20,15), 40,0,Color.BLACK);
```


# Rectangle

Rectangle är en datatyp som beskriver rektanglar. De kan användas både för att rita ut rektanglar på skärmen och för att [kolla kollisioner](/annat/raylib/kollisioner).

```csharp
// Skapar två rektanglar
Rectangle r1 = new Rectangle(10,10,50,20);
Rectangle r1 = new Rectangle(5,5,50,20);

// Ritar ut en rektangel
Raylib.DrawRectangleRec(r1, Color.SKYBLUE);

// Kollar ifall två rektanglar överlappar varandra
bool isColliding = Raylib.CheckCollisionRecs(r1, r2);
```

Man kan ändra på en rektangels egenskaper i efterhand.

```csharp
r1.X += 3;
r1.Y = 90;
r1.Width = 50;
r1.Height = 30;
```

## Rectangle och List

Rectangles är inte [klasser](/klasser-och-objektorientering/klasser-och-instanser) – de är Structs. Det betyder att om man lagrar rectangles i en lista, så kan man inte ändra rektanglarna direkt i listan.

```csharp
List<Rectangle> rects = new List<Rectangle>();

rects.Add(new Rectangle());
rects.Add(new Rectangle());
rects.Add(new Rectangle());
rects.Add(new Rectangle());

// SÅHÄR KAN MAN INTE GÖRA
rects[1].X = 5;

// GÖR SÅHÄR ISTÄLLET
Rectangle tmp = rects[1];
tmp.X = 5;
rects[1] = tmp;
```


# Kollisioner

## CheckCollisionRecs()

Tar emot två [Rectangles ](/annat/raylib/rectangle)som parametrar och returnerar true om de överlappar, false om de inte gör det.

```csharp
Rectangle playerRect = new Rectangle(5,5,10,10);
Rectangle enemyRect = new Rectangle(10,10,10,10);

bool areOverlapping = Raylib.CheckCollisionRecs(playerRect, enemyRect); // true
```

## GetCollisionRec()

Tar emot två [Rectangles](/annat/raylib/rectangle) som parametrar och returnerar en Rectangle som motsvarar överlappet mellan dem.

```csharp
Rectangle playerRect = new Rectangle(50,50,100,100);
Rectangle enemyRect = new Rectangle(100,100,100,100);
Rectangle overlap = Raylib.GetCollisionRec(playerRect, enemyRect);

Raylib.DrawRectangleRec(playerRect, Color.RED);
Raylib.DrawRectangleRec(enemyRect, Color.BLUE);
Raylib.DrawRectangleRec(overlap, Color.ORANGE);
```

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHmNgpRz-b16wpwGwZI%2F-MVNgoLuQfzpkKK_bIKU%2F-MVNjKjAtFjx_GqmDAOd%2Fimage.png?alt=media\&token=92e8f9c1-9a13-4e69-96ea-93399b0c2006)

## CheckCollisionCircles()

Tar emot två [vektorer ](/grundlaggande/vektorer-numerics)som beskriver två cirklars mittpunkter, och två floats som beskriver cirklarnas radie, och returnerar true om de överlappar, false om de inte gör det.

```csharp
Vector2 playerPos = new Vector2(10,10);
Vector2 enemyPos = new Vector2(20,20);

// true
bool areOverlapping = Raylib.CheckCollisionCircles(playerPos, 10, enemyPos, 15);
```

## CheckCollisionCircleRec()

Tar emot en positions[vektor](/grundlaggande/vektorer-numerics) och en radie för en cirkel, och en [Rectangle](/annat/raylib/rectangle). Returnerar true om rektangeln och cirkeln överlappar varandra, false om de inte gör det.

```csharp
Rectangle playerRect = new Rectangle(5,5,10,10);
Vector2 enemyPos = new Vector2(20,20);

// true
bool areOverlapping = Raylib.CheckCollisionCircleRec(enemyPos, 15, playerRect);
```

## CheckCollisionPointRec()

Tar emot en punkt i form av en positions[vektor](/grundlaggande/vektorer-numerics) samt en [Rectangle](/annat/raylib/rectangle). Returnerar true om punkten befinner sig inuti rektangeln, false om den inte gör det.

```csharp
Rectangle enemyRect = new Rectangle(10,10,10,10);

mousePos = Raylib.GetMousePosition();

bool areOverlapping = Raylib.CheckCollisionPointRec(mousePos, enemyRect))
```


# Kamera

## Camera2D

Kamera för 2D-spel

```csharp
Camera2D camera = new Camera2D(); // Skapa ny kamera
```

### zoom

Hur inzoomad kameran ska vara.

```csharp
  camera.Zoom = 1f; // Bestämma zoomvärdet till 1
```

{% hint style="warning" %}
OBSERVERA: Om du inte bestämmer värdet för zoomen, så kommer kameran att bete sig underligt. Ge alltid kameran zoomvärde 1 (eller något annat) manuellt!
{% endhint %}

### target

Den punkt i världen som kameran ska roteras kring, och som även dess zoom fokuseras på – samt den punkt dess offset ska utgå från.

```csharp
camera.Target = new Vector2(400, 300);
```

### offset

Kamerans offset är en 2d-vektor som beskriver hur långt från sin target kamerans övre vänstra hörn befinner sig – alltså hur långt den ska flyttas från sin ursprungsposition, relativt allt annat.

```csharp
float screenWidth = Raylib.GetScreenWidth();
float screenHeight = Raylib.GetScreenHeight();

// Gör så att kamerans target hamnar i mitten av skärmen
camera.Offset = new Vector2(screenWidth / 2, screenHeight/2);
```

### rotation

Hur roterad kameran ska vara.

```csharp
camera.Rotation = 45; // Roterar kameran 45 grader
```

### BeginMode2D() / EndMode2D()

Används för att, **mellan Raylib.BeginDrawing() och Raylib.EndDrawing()**, avgränsa vilka delar som ska ritas relativt kameran. I de flesta spel betyder det "hela själva spelet". Utanför BeginMode / EndMode ritar man ut UI-element och sådant som inte ska påverkas av kamerans rotationer och förflyttningar.

BeginMode2D vill ha en kamera som första parameter.

```csharp
Raylib.BeginMode2D(camera);

Raylib.ClearBackground(Color.LIGHTGRAY);
Raylib.DrawRectangle(390,290,10,10,Color.RED);

Raylib.EndMode2D();
```


# Ljud

Raylib har stöd för en hel del ljudformat, bland annat mp3, ogg och wave.

### InitAudioDevice()

Gör att Raylibs ljudsystem initieras.

```csharp
Raylib.InitAudioDevice();
```

### SetMasterVolume()

Bestämmer volymen överlag på en skala mellan 0.0 och 1.0.

```csharp
Raylib.SetMasterVolume(0.3f);
```

## Ljudeffekter

### Sound

En datatyp för ljudeffekter.

### LoadSound()

Läser in en ljudfil och placerar dess innehåll i minnet, redo att läsas av och spelas upp.

```csharp
Sound exampleSound = Raylib.LoadSound("woop_woop.ogg");
```

### PlaySound()

Spelar upp ett ljud

```
Raylib.PlaySound(exampleSound);
```

### PauseSound()

Pausar uppspelningen av ett ljud.

```csharp
Raylib.PauseSound(exampleSound);
```

### ResumeSound()

Fortsätter uppspelningen av ett pausat ljud.

```csharp
Raylib.ResumeSound(exampleSound);
```

### StopSound()

Avbryter uppspelningen av ett ljud.

```csharp
Raylib.StopSound(exampleSound);
```

### IsSoundPlaying()

Returnerar en bool – true om ljudet just nu spelas, annars false.

```csharp
bool isPlaying = Raylib.IsSoundPlaying(exampleSound);
```

### SetSoundVolume()

Bestämmer volym för ett ljud. Volymen anges som en float mellan 0.0 och 1.0.

```csharp
Raylib.SetSoundVolume(exampleSound, 0.35f);
```

## Musik

### Music

En datatyp för musikströmmar.

### LoadMusicStream()

Skapar en musikström baserad på en ljudfil. Hela ljudfilen läses inte in i minnet samtidigt, utan bara en liten bit i taget.

```csharp
Music exampleMusic = Raylib.LoadMusicStream("file_example_OOG_1MG.ogg");
```

### PlayMusicStream()

Aktiverar uppspelningen av en musikström.

```csharp
Raylib.PlayMusicStream(exampleMusic);
```

### PauseMusicStream()

Pausar uppspelningen av en musikström.

```csharp
Raylib.PauseMusicStream(exampleMusic);
```

### ResumeMusicStream()

Fortsätter uppspelningen av en pausad musikström.

```csharp
Raylib.ResumeMusicStream(exampleMusic);
```

### StopMusicStream()

Avbryter uppspelningen av musikströmmen helt.

```csharp
Raylib.StopMusicStream(exampleMusic);
```

### UpdateMusicStream()

Behöver köras varje frame. Kollar ifall mer data behöver laddas in från ljudfilen som musikströmmen är kopplad till, och gör det i så fall.

```csharp
Raylib.UpdateMusicStream(exampleMusic);
```

### IsMusicPlaying()

Returnerar en bool – true om musikströmmen just nu spelas, annars false.

```csharp
bool isPlaying = Raylib.IsMusicPlaying(exampleMusic);
```

### SetMusicVolume()

Bestämmer volym för en musikström. Volymen anges som en float mellan 0.0 och 1.0.

```csharp
Raylib.SetMusicVolume(exampleMusic, 0.75f)
```


# Raylib-CSharp\*

Raylib är från början ett bibliotek till C++, och Raylib-cs är inte det enda sättet att koppla Raylib till C#. **Raylib-CSharp** är ett annat paket, som funkar delvis annorlunda.

## Separata bibliotek

Raylib-CSharp är mer uppdelat än Raylib-cs. Varje kategori av funktioner har sitt eget bibliotek, som man måste inkludera via [using](/grundlaggande/anvaenda-bibliotek-using).

```csharp
using System.Numerics;
using Raylib_CSharp.Colors;
using Raylib_CSharp.Rendering;
using Raylib_CSharp.Windowing;

Window.Init(800, 600, "Hello");

Vector2 position = new (400, 300);

while (!Window.ShouldClose())
{
  Graphics.BeginDrawing();
  Graphics.ClearBackground(Color.Green);

  Graphics.DrawCircleV(position, 40, Color.Black);

  Graphics.EndDrawing();
}
```

## Funktioner

| Raylib-cs                | Raylib-CSharp            | Bibliotek      |
| ------------------------ | ------------------------ | -------------- |
| Raylib.InitWindow        | Window\.Init             | Windowing      |
| Raylib.SetTargetFPS      | Time.SetTargetFPS        | Raylib\_CSharp |
| Raylib.WindowShouldClose | Window\.ShouldClose      | Windowing      |
| Raylib.BeginDrawing      | Graphics.BeginDrawing    | Rendering      |
| Raylib.EndDrawing        | Graphics.EndDrawing      | Rendering      |
| Raylib.ClearBackground   | Graphics.ClearBackground | Rendering      |
| Raylib.DrawRectangle     | Graphics.DrawRectangle   | Rendering      |
| Raylib.DrawCircle        | Graphics.DrawCircle      | Rendering      |
| Raylib.DrawLine          | Graphics.DrawLine        | Rendering      |
|                          |                          |                |

Varianter av funktionerna – DrawRectangleRec, DrawRectangleLines osv finns såklart också.

## Datatyper

| Struct    | Bibliotek       |
| --------- | --------------- |
| Rectangle | Transformations |
| Color     | Colors          |
| Texture   | Textures        |
| Image     | Images          |


# MonoGame \[…]

Monogame är ett ramverk för att göra spel – lite som [Raylib ](/annat/raylib)men lite mer komplicerat. Däremot är det från början skrivet för C#, all dokumentation och alla tutorials för MonoGame är skrivna för C# vilket gör det lite lättare att hitta hjälp.

{% hint style="info" %}
Mer info kommer, sidan är bara påbörjad
{% endhint %}

## Installera MonoGame och MCGB Editor

Kör följande kommandon i terminalen:

```
dotnet new install MonoGame.Templates.CSharp
dotnet tool install --global dotnet-mgcb-editor
```

Det första kommandot installerar MonoGames-mallarna så att du kan skapa nya MonoGame-projekt.

Det andra kommandot installerat verktyget MCGB editor, som du kommer att behöva för att lägga in bilder och annat innehåll (MCGB står för Monogame Content Builder Tool).


# Monogame-projekt\*

## Skapa ett projekt

Skapa ett nytt ".Net Project" som vanligt, men istället för Console App väljer du **MonoGame Cross-Platform Desktop Application**.

## Projektstruktur\*

* Program.cs
* Game-klass
  * Initialize
  * LoadContent
  * Update
  * Draw


# MCGB Editor\*


# Input\*


# Grafik\*

## GraphicsDevice

En abstraktion som ger tillgång till renderingssystemet.

### Clear()

Rensar skärmen/fönstret, använder färgen som anges som parameter.

```csharp
GraphicsDevice.Clear(Color.CornflowerBlue);
```

## Color

Datatyp som MonoGame använder för att hantera förg.

```csharp
Color hotPink = new(255, 105, 180);
Color semiTransparentWhite = new(255, 255, 255, 128);
```

Värdena som anges som parametrar är mängden rött, grönt och blått som färgen ska innehålla, på skalan 0–255. Anges ett fjärde värde så tolkas det som mängden "Alpha", alltså genomskinlighet där 0 är helt genomskinligt och 255 är helt ogenomskinligt.

## Texture2D

Ett Texture2D-objekt är en tvådimensionell bild. Oftast skapas de genom att man laddar in resources som man tidigare förberett i [MCGB Editor\*](/annat/monogame/mcgb-editor).

```csharp
Texture2D hero = Content.Load<Texture2D>("heroSprite");
```

Man kan också skapa nya Texture2Ds. När de skapas är de då helt tomma.

```csharp
// Skapa en Texture2D som är 1x1 i storlek
Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1);
```

### GetData\<Color>()

Avancerat – Fyller en array med färgdatan från texturen. Första parametern ska vara den array som fylls med datan; den måste ges samma storlek som det totala antalet pixlar i texturen.

```csharp
// Skapa en array av rätt storlek
Color[] pixels = new Color[hero.Height * hero.Width]

// Hämta datan in i arrayen
hero.GetData<Color>(pixels);
```

Arrayen är endimensionell – alla pixlar ligger efter varandra. Den är organiserad i rader, så först ligger alla pixlar på bildens första rad, sedan alla på bildens andra rad, sedan tredje raden, osv.

För att byta färg på en enskild pixel i arrayen används sedan vanlig indexering, och datatypen här är Color.

### SetData()

Avancerat – Motsvarigheten till GetData(). Används för att stoppa in en array med färgdata in i en Texture2D.

```csharp
hero.SetData<Color>(pixels);
```

## SpriteBatch

2D-grafik i Monogame ritas ut med SpriteBatches. När man skapar ett nytt Monogame-projekt får man automatiskt en SpriteBatch-variabel i Game1-klassen:

```csharp
private SpriteBatch _spriteBatch;
```

Och den initieras och kopplas till sysyemets renderingssystem (GraphicsDevice) i LoadContent:

```csharp
protected override void LoadContent()
{
  _spriteBatch = new SpriteBatch(GraphicsDevice);
}
```

Därefter kan den användas i Draw() för att rita ut Texture2D-objekt till MonoGame-fönstret.

```csharp
protected override void Draw(GameTime gameTime)
{
  GraphicsDevice.Clear(Color.CornflowerBlue);

  _spriteBatch.Begin();
  _spriteBatch.Draw(pixel, rectangle, Color.Red);
  _spriteBatch.End();
    
  // ...
  base.Draw(gameTime);
}
```

### Begin()

Aktiverar en SpriteBatch och gör den redo för att börja rita ut sprites till skärmen.

```csharp
_spriteBatch.Begin();
```

### End()

Avslutar en SpriteBatch' ritande för den här bildrutan.

```csharp
_spriteBatch.End();
```

### Draw()

Ritar ut en Texture2D till skärmen. Första parametern är alltid den textur som ska ritas ut och den sista är den färg som texturen ska färgas med. Använd `Color.White` om du bara vill använda texturens normala färger.

```csharp
Rectangle rect = new (10,20,64,64);
Vector2 pos = new(100,20);

// Rita ut 'hero' och passa in den i rektangeln 'rect'
_spriteBatch.Draw(hero, rect, Color.White);

// Rita ut 'monster' på positionen som anges av vektorn 'pos'
_spriteBatch.Draw(monster, pos, Color.White);
```

Vill man bara rita ut en del av en Texture2D så kan man ange en extra rektangel som beskriver vilken del som ska klippas ut och visas.

```csharp
Rectangle rect = new (10,20,64,64);
Rectangle localRect = new(0,0,16,16);

// Rita ut den del av 'spritesheet' som finns inom 'localRect' och 
// passa in den i rektangeln 'rect'
_spriteBatch.Draw(spriteSheet, rect, localRect, Color.White);
```

Det finns även andra varianter av Draw() som inte dokumenteras här.


# Kollisioner


# Ljud\*


# Nätverk och internet \[…]

* [CRUD, HTTP och REST](/annat/naetverk-och-internet/rest-och-crud)
* [URL:er och REST](/annat/naetverk-och-internet/url-er-och-rest)
* [RESTful client](/annat/naetverk-och-internet/restful-client)
* [RESTful server](/annat/naetverk-och-internet/restful-server)


# CRUD, HTTP och REST

Se [Databaser ](/annat/databaser)och framför allt [CRUD](/annat/databaser#crud).

## HTTP

HyperText Transfer Protocol. En standard för att föra över information via nätverk. Är grunden till internet.

HTTP bygger på request-response-modellen:

1. Klienten skickar ett request-meddelande till servern. I det specifieras vad det är man vill göra och vilken resurs man vill göra det med. Till exempel: hämta en specifik html-fil eller läsa av en specifik pryl ur en databas.
2. Servern svarar med ett response-meddelande. I det specifieras vad resultatet blev när servern försökte utföra det klienten bad om.

### Header och body

Varje HTTP-meddelande består av en header och en body. Bodyn kan vara tom, och det är den ofta när man t.ex. försöker hämta en hemsida som inte finns eller när man inte försökte hämta något alls.

Headern innehåller allmän data och information om meddelandet. Här finns till exempel info om vilken version av HTTP som används, serverns/klientens mjukvara, när meddelandet skickades etc.

Request-meddelanden innehåller alltid en "metod" – motsvarar ungefär verb. Metoden avgör vilken sorts operation det är man försöker göra – POST, PUT, GET etc.

Response-meddelanden innehåller alltid en respons-kod som talar om ifall requesten lyckades eller om något gick fel. Det kan t.ex. vara kod 200 ("ok") eller 404 ("not found").

### POST

Används för att skicka in en ny resurs till en server.

### GET

Används för att hämta en resurs från en server.

### PUT

Används för att ersätta en resurs som redan finns på en server med en ny resurs.

### DELETE

Används för att ta bort en resurs från en server.

## REST

REST är en förkortning av Representational State Transfer. Förenklat kan man säga att REST innebär att man utför [CRUD-operationer](/annat/databaser#crud) med hjälp av HTTP-kommandon på ett standardiserat sätt.

| CRUD   | HTTP   |
| ------ | ------ |
| Create | POST   |
| Read   | GET    |
| Update | PUT    |
| Delete | DELETE |

Så för att till exempel läsa/hämta information om en specifik artikel så kan man i ett REST-API skicka en HTTP-request med GET som metod till <https://www.somenews.net/api/articles/45> och då får man ett HTTP-response som innehåller artikel nummer 45s data.

Och för att lägga in en ny artikel skulle man då kunna skicka en HTTP-request med POST som metod till <http://www.somenews.net/api/articles>. Då skulle man också inkludera den nya artikelns data i requesten. Som svar skulle man då kunna få ett HTTP-response med statuskoden Ok, och då vet man att artikeln lagts till.

Exakt hur requests ska se ut beror på vad den som bygger servern bestämmer. Det finns inget automatiskt i att det är just /api/articles som gäller, det skulle lika gärna kunnat vara /cyberzone/fluff/gauntlet eller vad som helst.


# URL:er och REST

En URL på internet har kan till exempel se ut såhär:

```
http://test.stapi.co/api/v1/rest/animal?uid=ANMA0000032338
```

Den består av följande delar:

* **Protokollet:** `http`
* **Domänen:** `test.stapi.co`
  * **Domännamn:** `stapi`
  * **Underdomän:** `test`
  * **Toppdomän:** `co`
* **Mappar:** `api, v1, rest`
* **Resurs:** `animal`
* **Parametrar:** `uid=ANMA0000032338`

## REST-endpoint

En "REST-endpoint" är den delen av REST-URL:en som är gemensam för alla anrop till API:et. För Star Trek-API:t är endpointen denna:

```
http://test.stapi.co/api/v1/rest/
```

Den består alltså av protokoll, domännamn och ofta en eller flera mappar.

## REST-resurs

En REST-resurs är den del av databasen eller systemet som API:et ger tillgång till som man vill hämta information från. Ett exempel från Star Trek API:t är t.ex. "animal". Om man då lägger ihop endpoint plus resurs så får man då:

```
http://test.stapi.co/api/v1/rest/animal
```

I vissa API:er används bara endpoints och resurser. I PokeApi till exempel anger man namnet på den pokemon man vill ha information om som en resurs:

```
https://pokeapi.co/api/v2/pokemon/ditto
```

## Parametrar och REST

Parametrar kan ge ytterligare information om t.ex. Det är generellt här man anger sin API-nyckel för databaser som kräver en sådan. Det finns API:er som använder parametrar för att specificera vilken resurs man vill hämta eller modifiera, men det är strikt taget inte riktigt REST då.

Parametrar skrivs genom att man först har ett frågetecken som separerar parametrarna från resten, och sedan par av parameter+värde. Paren separeras från varandra med & och parametern separeras från värdet med ett likamed-tecken.

```
http://stapi.co/api/v1/rest/animal?uid=ANMA0000032338
```


# RESTful client\*

## Snabbstart

Nedanstående exempelkod skapar ett klientobjekt och ett requestobjekt, skickar requesten genom klienten för att få ett response, och deserialiserar response-objektets text till en instans av Pokemon-klassen.

```csharp
using System.Text.Json;

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://pokeapi.co/api/v2/");
HttpResponseMessage result = client.GetAsync("pokemon/ditto").Result;
Pokemon p = JsonSerializer.Deserialize<Pokemon>(result.Content.ReadAsStringAsync().Result);

// Alternativ till de två sista raderna:

Pokemon p = result.Content.ReadAsAsync<Pokemon>().Result;
```

## HttpClient

En klass som sköter kommunikationen med API-servern.

```csharp
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://pokeapi.co/api/v2/");
```

Skapar ett klientobjekt som kommer att skicka requests till PokeAPI.

BaseAddress behöver egentligen inte ändras, men det är praktiskt ifall man ska göra många anrop till url:er som börjar på samma sätt.

### GetAsync, PostAsync, PutAsync, DelAsync

Dessa metoder används för att skicka en request till en RESTful API-server och leverera resultatet.

Välj rätt metod:

| Metod     | HTTP-metod | Aktivitet               |
| --------- | ---------- | ----------------------- |
| PostAsync | POST       | Skapa en ny resurs      |
| GetAsync  | GET        | Hämta data om en resurs |
| PutAsync  | PUT        | Ändra en resurs         |
| DelAsync  | DELETE     | Ta bort en resurs       |

Metoderna tar alla emot en url-sträng och returnerar en [Task](/annat/threading/task). Denna Task ger sedan ifrån sig, som Result, ett [HttpResponseMessage](#httpresponsemessage).

```csharp
HttpResponseMessage response = client.GetAsync("pokemon/snorlax").Result;
```

Post och Put vill också ha en *body* – alltså det som ska skickas in.

```csharp
using System.Net.Http.Json;

// ---

// Serialisera snorlax till JSON och skicka som body
JsonContent jsonBody = JsonContent.Create<Pokemon>(snorlax);
HttpResponseMessage response = client.PostAsync("pokemon/snorlax", jsonBody).Result;
```

Många metoder här är [asynkrona metod](/annat/threading/task). Med andra ord går det att använda await istället för .Result om man är i en asynkron metod.

```csharp
async string GetPokemon(string pokemonName)
{
  Task<HttpResponseMessage> task = client.GetAsync($"pokemon/{pokemonName}");
  
  // gör något annat medan klienten hämtar resultatet
  
  await task;
  return task.Result;
}
```

## HttpResponseMessage

Ett HttpResponseMessage-objekt innehåller det svar servern skickat tillbaka.

### StatusCode

I response-objektet ingår en StatusCode. Dess datatyp är en [Enum](/grundlaggande/datatyper/enum) som heter HttpStatusCode och finns i biblioteket System.Net. Dess möjliga värden är alla existerande, definierade statuskoder från HTTP-standarden. Till exempel Ok och NotFound.

```csharp
  if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
  {
    Console.WriteLine("Not found!");
  }
```

För att slippa skriva System.Net hela tiden kan du använda ett using-statement högst upp i filen:

```csharp
using System.Net;
```

### Content

Content är det "innehåll" servern svarat med.

```csharp
// Hämtar content som string-data
string jsonText = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(jsonText);
```

Ofta är Content JSON eller XML-format, och då kan informationen deserialiseras till ett objekt antingen via [JSON-deserialisering](https://csharp.progdocs.se/annat/naetverk-och-internet/pages/-MTaHhqTfoWFY4TozPsH#jsonserializer.deserialize) eller [XML-deserialisering](/filhantering/serialisering/xml-serialisering#deserialize).

Om det är JSON så finns ett enklare sätt – inkludera `System.Net.Http.Json` och använd `ReadFromJsonAsync` istället för `ReadAsStringAsync`.

```csharp
using System.Net.Http.Json;

HttpClient client = new();
client.BaseAddress = new("https://pokeapi.co/api/v2/");
HttpResponseMessage response = client.GetAsync("pokemon/snorlax").Result;
Pokemon p = response.Content.ReadFromJsonAsync<Pokemon>().Result;
```

## Kommunicera med en lokal server

Om du vill anropa en lokal server (localhost) men får ett felmeddelande om ett SSL-fel, så kan du kör denna kod i terminalen för att det ska fungera:

```powershell
dotnet dev-certs https --trust
```

## Öppna databas-API:er

* [Pokemon API](https://pokeapi.co/)
* [Digimon API](https://digimon-api.herokuapp.com/)
* [Star Wars API](https://swapi.py4e.com/)
* [Star Trek API](http://stapi.co/)
* Steam-API
  * [Skaffa en API-nyckel](https://steamcommunity.com/dev/apikey)
  * [Dokumentation](https://partner.steamgames.com/doc/webapi)
* [Marvel API](https://developer.marvel.com/) (kräver en del egna efterforskningar och krångel – hög svårighetsgrad!)


# Thunder

VSCode-pluginet [Thunder Client](https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client) låter oss göra REST-anrop till servrar utan att programmera en klient.

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FV9hjIyHkaQyT3Pnsz8z3%2Fimage.png?alt=media&amp;token=19b8eaa4-9a5a-4aba-9591-05ee320b7e84" alt=""><figcaption></figcaption></figure>

Den är ganska enkel att använda.

* Gå till Thunder client i VSCode.
* Välj din metod, t.ex. GET eller POST
* Skriv in din URL
* Klicka SEND
* Resultatet ser du under Response.

## Skicka JSON-data

Om man ska skicka in data till ett API den här vägen, behöver den skrivas in i requestens Body-del.

Antagligen behöver datan också formateras som JSON. Om man till exempel vill POST:a in en ny Pokemon in i exempel-API-servern vars modeller beskrivs under Models/dataklasser så skriver man såhär i Body:

```javascript
{
    "name": "Nyarlathotep"
}
```

Ofta kan man undersöka den output man får från GET för att se hur JSON-datan behöver vara formaterad.


# RESTful server (Minimal API)

Nedan är instruktioner för att skapa en enkel API-server som svarar på GET-anrop.

[Här finns Microsofts officiella snabbreferens.](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis)

## Skapa projektet

Skapa projektets solution som vanligt, men välj **ASP.NET Core Empty** som projekttyp istället för **Console application**.

## Ett minimalt projekt

Nedanstående är ett absolut minimalt, enkelt projekt som helt enkelt skickar "Hello World!" till den som skickar en get-request till programmet:

{% code lineNumbers="true" %}

```csharp
// Skapa en webbapplikation-instans
WebApplication app = WebApplication.Create(args);

// Använd HTTPS när det går
app.UseHttpsRedirection();

// När en GET-request kommer för "/" så svarar servern med det som 
//  returneras från GimmeHello
app.MapGet("/", GimmeHello);

// Kör webbapplikationen
app.Run();

// Metoden som ska köras när någon gör en GET-request
static string GimmeHello()
{
  return "Hello World!";
}
```

{% endcode %}

## WebApplication

WebApplication-objektet är det som sköter kommunikationen över webben och som ser till att anropa rätt metod när rätt HTTP-request skickas till programmet.

### MapGet(), MapPost(), MapPut() och MapDelete()

Dessa metoder kopplar en [HTTP-metod](/annat/naetverk-och-internet/rest-och-crud) (GET, POST, PUT eller DELETE) och en [REST-resurs](/annat/naetverk-och-internet/url-er-och-rest#rest-resurs) till en specifik C#-metod. Detta kallas "mapping".

```csharp
app.MapGet("/pokemon/", GimmePokemon);
```

Om någon sedan gör en request till serverns adress, och requesten har metoden GET och inkluderar /pokemon/ (t.ex. **<https://localhost:7174/pokemon>**, så kommer det response som skickas tillbaka vara det som returneras från GimmePokemon-metoden.

MapGet kopplar till GET-requests, MapPost till POST-requests, MapPut till PUT-requests och MapDelete till DELETE-requests.

C#-metoden kan vara en statisk metod, en instansmetod eller ett [Lambda-uttryck](/grundlaggande/delegates#lambdas).

```csharp
app.MapGet("/hello/", () => "Say hello!");
```

### Parametrar

C#-metoden kan förses med parametervärden via URL:en.

```csharp
app.MapGet("/double/{num}/", Double);

static string Double(int num)
{
  return (num * 2).ToString();
}
```

När man i exemplet ovan besöker t.ex. **<https://localhost:7174/double/7>** så blir det 14 som skickas tillbaka som HTTP-response.

Detta används ofta för att välja vilken data som ska skickas – en parameter kan till exempel vara ett unikt ID eller namnet på ett objekt (en användare eller ett dokument). Då skriver man en metod som letar igenom en lista eller en databas efter rätt ID, och returnerar den datan. Ofta skickas då datan som ett objekt.

### Returnera Objekt som JSON

Om metoden som mappas returnerar ett objekt, så kommer det objektet [serialiseras](https://csharp.progdocs.se/annat/naetverk-och-internet/pages/-MTaHhqTfoWFY4TozPsH#jsonserializer.serialize) till [JSON](/filhantering/filformat/json) innan det skickas tillbaka som ett [HTTP-response](/annat/naetverk-och-internet/rest-och-crud#http).

{% code title="Hero.cs" %}

```csharp
public class Hero
{
  public string Name { get; set; }
  public int Hitpoints { get; set; }
}
```

{% endcode %}

<pre class="language-csharp"><code class="lang-csharp"><strong>app.MapGet("/hero/superman/", GetSuperman);
</strong>
static Hero GetSuperman()
{
  Hero h = new Hero();
  h.Name = "Superman";
  h.Hitpoints = 100;
  return h;
}
</code></pre>

Resultatet om man skickar en GET-request till **/hero/superman**:

```json
{
  "name": "Superman",
  "hitpoints": 100
}
```

### Skicka in nya objekt via POST/PUT och JSON

För att kunna hantera att nya objekt skickas till serverprogrammet, mappa POST eller PUT till en metod som har en parameter av den datatyp [JSON](/filhantering/filformat/json)-koden ska [deserialiseras ](https://csharp.progdocs.se/annat/naetverk-och-internet/pages/-MTaHhqTfoWFY4TozPsH#jsonserializer.deserialize)till.

```csharp
app.MapPost("/hero/new/", AddNewHero);

static void AddNewHero(Hero h)
{
  heroList.Add(h);
  Console.WriteLine($"Added hero {h.Name} to the list"
}
```

När en användare då skickar in JSON-kod som [body ](/annat/naetverk-och-internet/rest-och-crud#header-och-body)i sin HTTP-request till servern, så deserialiseras koden automatiskt till en instans av klassen och resultatet hamnar i parametern när metoden anropas.

### Results

För att skicka någon annan statuskod än OK, gör så att C#-metoderna returnerar Results.

```csharp
static IResult GetBatman()
{
  Hero h = new Hero();
  h.Name = "Batman";
  h.Hitpoints = 30;
  return Results.Ok(h);
}
```

Det finns en hel del olika HTTP-statuskoder, till exempel:

* **Results.Ok** – allt gick bra.
* **Results.NotFound** – det du frågade efter fanns inte.
* **Results.BadRequest** – den request du skickade kunde inte tolkas, eller innehöll fel.

## Komma åt servern från andra datorer

Normalt sett kan servern inte kommas åt från andra datorer än den den körs på; den kallas "localhost". För att också kunna komma åt den från andra datorer på samma nätverk, lägg till en URL med wildcard (\*):

```csharp
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://*:3000");
```

Ovanstående gör att man kan komma åt servern både genom url:en localhost:3000 (på den lokala datorn) och genom att skriva datorns ip-nummer följt av 3000 (på den lokala datorn eller på någonnannan dator på samma nätverk).

## WebApplicationBuilder

Ifall man vill göra något lite mer avancerat med sin WebApplication, så använder man en WebApplicationBuilder för att konstruera den. Buildern fungerar då som en "fabrik" – man skapar den, gör inställningar, och säger sedan åt den att skapa en WebApplication.

```csharp
WebApplicationBuilder builder = WebApplication.CreateBuilder();

// Lägg till funktionalitet för Swagger/OpenAPI
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Bygg själva applikationen
WebApplication app = builder.Build();
```

## Använda HTTPS

Om du får problem med att komma åt din server, via webbläsare eller via klienter skrivna i C#, så kan det här behövas.

Börja med att generera och lägga till ett certifikat för lokal utveckling och debuggning. Kör i terminalen:

```powershell
dotnet dev-certs https
dotnet dev-certs https --trust
```

Lägg sedan till URL:er för https:

```
app.Urls.Add("https://localhost:3000");
app.Urls.Add("https://*:3000");
```

Nu bör HTTPS fungera – åtminstone på din egna dator.

## LaunchSettings.json

(Kommer…)


# Swagger och OpenAPI

OpenAPI – även kallat Swagger – är ett sätt att snabbt och enkelt dokumentera det API servern tillhandahåller så att den som försöker använda APIt vet vad som kan göras och hur. Swagger UI get ett grafiskt webbgränssnitt för att förenkla testning av APIt.

Stöd för OpenAPI/Swagger sker i C# normalt genom biblioteket Swashbuckle, som ingår som standard i alla Minimal API-projekt (kolla själv i csproj-filen).

## Lägga till Swagger

Börja med att se till så att WebApplication-objektet har tillgång till rätt Services – EndpointsApiExplorer och SwaggerGen.

```csharp
WebApplicationBuilder builder = WebApplication.CreateBuilder();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Skapa en webbapplikation-instans
WebApplication app = builder.Build();
```

Därefter aktiveras Swagger enkelt genom metoden UseSwagger.

```csharp
app.UseSwagger();
```

Om man bara vill att Swagger ska vara aktiverat medan man utvecklar servern så kan man lägga in UseSwagger i en if-sats:

```csharp
if (app.Environment.IsDevelopment())
{
  app.UseSwagger();
}
```

Om man nu besöker serverns url följt av /swagger/v1/swagger.json så får man en json-representation av serverns endpoints. Den är i första hand tänkt att läsas av andra maskiner (klienter), inte människor.

```json
{
  "openapi": "3.0.1",
  "info": {
    "title": "My awesome server",
    "version": "1.0"
  },
  "paths": {
    "/": {
      "get": {
        "tags": [
          "ApiTest"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": { }
}
```

## Konfigurera Swagger

Man kan göra inställningar som ändrar metadatan i Swagger-json-datan genom att ändra i AddSwaggerGen-metodanropet:

```csharp
builder.Services.AddSwaggerGen(c =>
  {
    c.SwaggerDoc("v1", new() { 
      Version = "1.0", 
      Title = "My awesome server" });
  }
);
```

Det man lägger till är alltså ett lambda-uttryck som matchar en delegat som tar emot ett SwaggerGenOptions-objekt (c, i det här fallet) som vi sedan kan göra ändringar i. Den ändring vi gör är att vi kör SwaggerDoc-metoden där vi lägger till ett dokument som heter "1.0" i vilken vi ändrar metadatan Version och Title.

## SwaggerUI

För att aktivera Swagger UI, anropa metoden UseSwaggerUI(). Det brukar göras på samma ställe som UseSwagger().

```csharp
app.UseSwagger();
app.UseSwaggerUI();
```

Om man nu besöker serverns URL följt av /swagger så möts man av ett snyggt UI som visar vilka endpoints etc som API:et har. Här kan man dessutom testa API:et.


# RESTful server (Web API) \[…]

[Controllers ](/annat/naetverk-och-internet/restful-server/controllers)| [Models/dataklasser](/annat/naetverk-och-internet/restful-server/models) | [Tester med RESTer](/annat/naetverk-och-internet/restful-server/tester-med-rester) | [Thunder](/annat/naetverk-och-internet/thunder)

Nedan är instruktioner för att skapa en enkel API-server som svarar på GET-anrop.

## Skapa projektet

Skapa projektets solution som vanligt, men välj **.NET Core Web API** som projekttyp istället för **Console application**.

### Rensa bort Weather Forecast-delarna

* Ta bort **WeatherForecast.cs**
* Ta bort **WeatherForecastController.cs**, som ligger i Controllers-mappen.

## Controller

Skapa en ny klass i Controllers-mappen. Döp den till SomethingController. Du kan byta ut "Something" mot något annat om du vill.

```csharp
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController]
public class SomethingController : ControllerBase
{
  [HttpGet]
  public ActionResult Get()
  {
    return Ok("Hej");
  }
}
```

Route och ApiController är *decorators*. De talar om att den här klassen är en API-controller och att den ska kopplas till url:en api/Something. \[controller] i Routen byts alltså ut automatiskt mot det som står innan Controller i klassens namn.

HttpGet är också en decorator, som talar om att metoden Get ska anropas när någon försöker hämta data från controllern (via url:en).

ActionResult är en klass som tillhandahålls av .Net och innehåller allt sådant som ett server-svar brukar behova innehålla.

Ok är en metod som returnerar ett färdigt ActionResult med HTTP-koden "ok". Resultatets meddelande blir det som anges som det första parametervärdet, i det här fallet alltså "hej".

## Köra och testa servern

### Gör så servern kan nås från andra datorer (behöver göras 1 gång)

* I Properties-mappen, öppna LaunchSettings.json
* Let rätt på "applicationUrl" en bit ner. Inte den som ligger i \[iissettings], utan den som ligger kring rad 25.
* Ändra localhost till \*
* Ändra också "launchBrowser" till false.

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHmNgpRz-b16wpwGwZI%2F-MISxvYqmVSicY4Fjadl%2F-MITjmEFPGk-3SCYoIK6%2Fimage.png?alt=media\&token=b8052571-28d3-4183-b1b9-d23098fd9e1a)

### Starta servern

* Tryck på F5 som vanligt.

### Titta på API:et i en webbläsare.

* Starta t.ex. Chrome medan servern körs.
* Gå till `https://localhost:5001/api/Something`


# Controllers

Controllers är klasser som kopplar ihop klientens HTTP-requests med serverns data, via lite egen logik.

Nedan – ett exempel på en controller som kopplar ihop GET-requests till url:en som slutar på /api/Something med metoden Get().

```csharp
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController]
public class SomethingController : ControllerBase
{
  [HttpGet]
  public ActionResult Get()
  {
    return Ok("Hej");
  }
}
```

## Attribut

Mer om attribut [här](/klasser-och-objektorientering/attribut).

### \[ApiController]

Dekorerar en klass. Meddelar API-serversystemet att denna klass är en API Controller och ska kunna ta emot requests.

{% code title="PokemonController.cs" %}

```csharp
[ApiController]
public class PokemonController : ControllerBase
{

}
```

{% endcode %}

### \[Route("thing")]

Dekorerar en klass eller en metod. Meddelar API-serversystemet att klassen eller metoden ska ta emot requests till en specifik "route". Exempel:

* <https://localhost:5001/api/pokemon> → routen är "api/pokemon"
* <https://www.test.com/hello/world> → routen är "hello/world"
* [https://192.168.1.100/number](https://www.google.com/url?q=https%3A%2F%2F192.168.1.100%2Fnumber\&sa=D\&sntz=1\&usg=AFQjCNHmakUtrDd1CIEFI8sA-zNgZhw2XA) → routen är "number"

{% code title="PokemonController.cs" %}

```csharp
[ApiController]
[route("hello/world")]
public class PokemonController : ControllerBase
{

}
```

{% endcode %}

När man dekorerar metoder med en Route, så läggs denna till klassens route med snedstreck mellan. I exemplet nedan blir routen som leder till metoden alltså hello/world.

{% code title="PokemonController.cs" %}

```csharp
[ApiController]
[route("hello")]
public class PokemonController : ControllerBase
{
  [HttpGet]
  [Route("world")]
  public ActionResult Getter()
  {
    // Routen till denna metod blir hello/world.
  }
}
```

{% endcode %}

### \[Route("\[controller]")]

När man dekorerar en klass, kan man skriva \[controller] inom hakparenteser inuti sin route. Det betyder att \[controller] i praktiken byts ut mot det som står innan Controller i klassens namn. Övrig text står kvar oförändrad.

{% code title="AngelController.cs" %}

```csharp
[ApiController]
[route("creatures/[controller]")]
public class AngelController : ControllerBase
{
  // Routen för denna klass blir creatures/angel.
}
```

{% endcode %}

### \[HttpGet]

Registrerar en metod som mottagare av GET-requests.

```csharp
[HttpGet]
public ActionResult Get()
{
  return Ok("Response");
}
```

Man kan också ange olika unika routes för olika Get-metoder. Det gör man genom att skriva in routen inom parenteser direkt i \[HttpGet].

{% code title="" %}

```csharp
[ApiController]
[route("creatures/[controller]")]
public class AngelController : ControllerBase
{
  [HttpGet("all")]
  public ActionResult Get()
  {
    // Ifall användaren skickar en request till routen 
    // creatures/angel/all så kommer den här metoden köras. 
  
    return Ok("Response for your request");
  }

  [HttpGet("n/{num}")]
  public ActionResult Get(int num)
  {
    // Ifall användaren skickar en request till routen 
    // creatures/angel/n/7 så kommer parametern 
    // "num" i den här metoden att få värdet "7".
    return Ok("Response for your request for #" + num);
  }

  [HttpGet("name/{name}")]
  public ActionResult Get(string name)
  {
    // Ifall användaren skickar en request till routen 
    // creatures/angel/name/gabriel så kommer parametern 
    // "name" i den här metoden att få värdet "gabriel".
    
    return Ok("Response for your request for " + name);
  }
```

{% endcode %}

En \[HttpGet]-metod brukar normalt returnera via Ok(), NotFound(), NoContent() eller BadRequest().

### \[HttpPost]

Registrerar en metod som mottagare av POST-requests. API-servern gör också ett försök att deserialisera inkommande JSON-data (angiven i requestens body) till rätt sorts instans.

```csharp
[HttpPost]
public ActionResult AddPokemon(Pokemon newPokemon)
{
  // Parametern newPokemon innehåller här förhoppningsvis – 
  // om det gick att deserialisera bodyn – 
  // en ny Pokemon-instans.
}
```

Även HttpPosts kan ges route-information precis som HttpGet.

```csharp
[HttpPost("secret")]
public ActionResult AddPokemon(Pokemon newPokemon)
{
  // Den här metoden körs om användaren lägger till /secret i slutet av
  // sin URL.
}
```

En \[HttpPost]-metod brukar normalt returnera via Ok() eller BadRequest().

{% hint style="warning" %}
**OBSERVERA:** För att servern ska kunna deserialisera inskickad JSON korrekt, måste Content-Type i requesten vara "application/json".
{% endhint %}

### \[HttpPut]

Registrerar en metod som mottagare av PUT-requests. API-servern gör också ett försök att deserialisera inkommande JSON-data (angiven i requestens body) till rätt sorts instans.

Skillnaden mellan POST och PUT är att när någon skickar en POST så förväntar de sig att det alltid ska skapas en ny sak i databasen, men vid PUT förväntar man sig att det bara skapas en ny sak ifall det inte finns en gammal, liknande, som kan uppdateras. Vad som bestämmer ifall det finns en gammal, liknande är du som programmerare. I en Pokemon-databas skulle man t.ex. kunna kolla om det redan finns en pokemon med samma unika ID-nummer.

```csharp
[HttpPut]
public ActionResult UpdatePokemon(Pokemon newPokemon)
{
  // Parametern newPokemon innehåller här förhoppningsvis – 
  // om det gick att deserialisera bodyn – 
  // en ny Pokemon-instans.
}
```

Även HttpPuts kan ges route-information precis som HttpGet.

```csharp
[HttpPut("n/{id}")]
public ActionResult UpdatePokemon(int id, Pokemon newPokemon)
{
  // Den här metoden körs om användaren lägger till /n/ och en siffra 
  // i slutet av sin URL, t.ex. /n/7.
  // Variabeln id får då värde 7.
  // Då kan man t.ex. byta ut den pokemonen som har id 7 mot den som
  // deserialiserats från http-bodyn.
}
```

En \[HttpPut]-metod brukar normalt returnera via Ok(), NotFound(), NoContent() eller BadRequest().

{% hint style="warning" %}
**OBSERVERA:** För att servern ska kunna deserialisera inskickad JSON korrekt, måste Content-Type i requesten vara "application/json".
{% endhint %}

### \[HttpDelete]

Registrerar en metod som mottagare av DELETE-requests.

```csharp
[HttpDelete("n/{id}"]
public ActionResult DeletePokemon()
{
  // Den här metoden körs om användaren lägger till /n/ och en siffra 
  // i slutet av sin URL, t.ex. /n/7.
  // Variabeln id får då värde 7.
  // Då kan man t.ex. ta bort den pokemon som har id 7 från databasen.
}
```

En \[HttpDelete]-metod brukar normalt returnera via Ok(), NotFound() eller BadRequest().

## ActionResponse-metoder

ActionResponse är en klass som beskriver vanliga HTTP-responses. Genom att använda de här färdiga metoderna, som returnerar färdiga ActionResponse-instanser, kan man göra det enkelt för sig.

Det finns sådana metoder för många HTTP-statuskoder – de nedan är bara exempel.

### Ok()

Ger ett ActionResult med HTTP-koden "ok" (200). Parametervärdet skickas som body.

```csharp
[HttpGet]
public ActionResult Get()
{
  return Ok("Response");
}
```

### Created()

Ger ett ActionResult med HTTP-koden "created" (201). Parametervärdet skickas som body.

Created betyder att servern skapat en ny sak, baserat på den request som skickades.

```csharp
[HttpPost]
public ActionResult AddPokemon()
{
  return Created("Response");
}
```

### NotFound()

Ger ett ActionResult med HTTP-koden "not found" (404). Parametervärdet skickas som body.

Not found betyder att den sak som efterfrågades inte finns.

```csharp
[HttpGet]
public ActionResult Get()
{
  return NotFound("Response");
}
```

### NoContent()

Ger ett ActionResult med HTTP-koden "no content" (202). Parametervärdet skickas som body.

No content betyder att servern tog emot requesten men att det inte finns någon content att visa.

```csharp
[HttpGet]
public ActionResult Get()
{
  return NoContent("Response");
}
```

### BadRequest()

Ger ett ActionResult med HTTP-koden "bad request" (400). Parametervärdet skickas som body.

Bad request betyder att det var något fel på den request klienten skickade till servern, och att servern inte kunde göra något vettigt med den.

```csharp
[HttpGet]
public ActionResult Get()
{
  return BadRequest("Response");
}
```


# Models/dataklasser

Models, eller modeller, är helt enkelt klasser som används av t.ex. en REST-server för att beskriva information. Ofta beskriver modellerna objekt som lagras i en databas av något slag, men det gås inte in på här.

## Modellklasser/dataklasser

Alla egenskaper som ska returneras av API:t måste vara publika [properties](/klasser-och-objektorientering/inkapsling-och-properties#properties).

{% code title="Pokemon.cs" %}

```csharp
public class Pokemon
{
  public string Name {get; set;}
}
```

{% endcode %}

## Returnera instanser som svar på requests

### JSON-serialiserade instanser

För att en \[HttpGet]-metod ska returnera en JSON-serialiserad version av en instans av en modellklass, behövs två saker:

* När man deklarerar metoden säger man att den ska returnera ActionResult\<Something>, där Something är namnet på klassen vars instanser ska serialiseras.
* När man kör Ok, så lägger man in en instans av den klassen inom parenteserna.

{% code title="PokemonController.cs" %}

```csharp
namespace WebApplication1.Controllers
{
  [Route("api/[controller]")]
  [ApiController]
  public class PokemonController : ControllerBase
  {
    [HttpGet]
    public ActionResult<Pokemon> Get()
    {
      Pokemon p = new Pokemon();
      p.Name = "Pikachu";

      return Ok(p);
    }
  }
}
```

{% endcode %}

Resultatet av ovanstående blir att följande JSON-kod skickas med i HTTP-response-bodyn:

```javascript
{
    "name": "Pikachu"
}
```

### JSON-serialiserade listor med instanser

Nedanstående kod skapar en lista med två pokemons, och returnerar den listan till klienter som anropar servern med ett GET-anrop.

{% code title="PokemonController.cs" %}

```javascript
namespace WebApplication1.Controllers
{
  [Route("api/[controller]")]
  [ApiController]
  public class PokemonController : ControllerBase
  {
    private static List<Pokemon> pList = new List<Pokemon>()
    {
      new Pokemon() {Name = "Pikachu"},
      new Pokemon() {Name = "Bulbasaur"}
    };

    [HttpGet]
    public ActionResult<List<Pokemon>> Get()
    {
      return Ok(pList);
    }
  }
}
```

{% endcode %}

### Mer specifika frågor

Om en användare ska kunna stoppa in mer specifik information i sin request, och svaret anpassas efter denna information, så behövs något sätt att läsa av den informationen i Controllern.

När man skapar sin Get-metod så kan man lägga till en `[Route]`, och specificera något som ska bli en variabel mellan måsvingar. Så i nedanstående exempel står det `[Route("{num}")]`, vilket betyder att det är den metoden som ska användas om något anges i slutet av request-url:en – t.ex. att url:en är `/api/pokemon/23`.

Det som står inom {} kommer att tolkas som data, som stoppas in som parameter i metoden – observera att metoden också har en "num". Det nummer som anges i request-url:en kommer alltså at omvandlas till en int och stoppas in som motsvarande parameter.

Hade det stått `[Route("/find/{num}")]` istället, så hade routen matchat t.ex. `/api/pokemon/find/23`. 23 hade fortfarande omvandlats till int-parametern num.

{% code title="PokemonController.cs" %}

```javascript
namespace WebApplication1.Controllers
{
  [Route("api/[controller]")]
  [ApiController]
  public class PokemonController : ControllerBase
  {
    private static List<Pokemon> pList = new List<Pokemon>()
    {
      new Pokemon() {Name = "Pikachu"},
      new Pokemon() {Name = "Bulbasaur"}
    };

    [HttpGet]
    public ActionResult<List<Pokemon>> Get()
    {
      return Ok(pList);
    }

    [HttpGet]
    [Route("{num}")]
    public ActionResult<Pokemon> Get(int num)
    {
      if (num > 0 && num < pList.Count)
      {
        return Ok(pList[num]);
      }
      else
      {
        return NotFound();
      }
    }
  }
}
```

{% endcode %}


# Tester med RESTer

Chrome-pluginet [RESTer](https://chrome.google.com/webstore/detail/rester/eejfoncpjfgmeleakejdcanedmefagga) låter oss göra REST-anrop till servrar utan att programmera en klient.

![](https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MHmNgpRz-b16wpwGwZI%2F-MJ1FYTOtsNWL1DYmray%2F-MJ1Hlim-w6F6w6IIfvK%2Fimage.png?alt=media\&token=b788ffff-dd7b-4a12-aaac-469fd39a192a)

Det är ganska enkelt att använda

* Gå in i RESTer
* Välj din metod, t.ex. GET eller POST
* Skriv in din URL
* Klicka SEND
* Resultatet ser du under Response.

## Skicka JSON-data

Om man ska skicka in data till ett API den här vägen, behöver den skrivas in i RESTers Body-del.

Antagligen behöver datan också formateras som JSON. Om man till exempel vill POST:a in en ny Pokemon in i exempel-API-servern vars modeller beskrivs under Models/dataklasser så skriver man såhär i Body:

```javascript
{
    "name": "Nyarlathotep"
}
```

Ofta kan man undersöka den output man får från GET för att se hur JSON-datan behöver vara formaterad.

{% hint style="warning" %}
**OBSERVERA:** Om du skickar in JSON-data, kom ihåg att lägga till en header som säger att Content-Type är "application/json".
{% endhint %}


# Linq

LINQ står får "Language-integrated query" och lägger dels till stöd för databas-frågor (queries) direkt i C#, och dels en serie metoder som gör det enklare att hitta specifik data i [samlingar](/klasser-och-objektorientering/generiska-klasser#samlingar).&#x20;

[Linq-metoder](/annat/linq/linq-metoder) | [Linq-queries](/annat/linq/linq-queries)


# Linq-metoder

Linq-biblioteket bygger ut existerande [samlings-datatyper](/klasser-och-objektorientering/generiska-klasser#samlingar) (som [List ](/klasser-och-objektorientering/generiska-klasser#list)och även [arrayer](/grundlaggande/listor-och-arrayer#array)) med nya metoder.

Ofta tar metoderna emot [delegater ](/grundlaggande/delegates)som parametrar, och ofta används då istället [Lambda-uttryck](/grundlaggande/delegates#lambdas).

Flera av metoderna returnerar en generisk samling av den Linq-specifika datatypen *Enumerable*, som i sin tur kan omvandlas till en lista genom att man anropar ToList().

### Hämta flera

#### Where()

Tar emot ett kriterium i form av en delegat eller ett Lambda-uttryck, och returnerar en Enumerator som innehåller alla föremål som matchar kriteriet.

```csharp
List<GameObject> objects = new();
objects.Add(new Enemy());

List<GameObject> lowHealth = 
  objects.Where(g => g.hp < 10)
  .ToList();
```

#### OfType<>()

Returnerar en Enumerable som innehåller alla föremål som är av en specifik datatyp. Väldigt användbart ifall man använt [polymorfism ](/klasser-och-objektorientering/polymorfism)för att lagra instanser av subklasser i en [samling ](/klasser-och-objektorientering/generiska-klasser#samlingar)där typvariabeln är basklassen.

```csharp
List<GameObject> objects = new();
objects.Add(new Enemy());

List<Enemy> enemies = objects.OfType<Enemy>().ToList();
```

### Hämta enstaka

#### First() / Last()

Returnerar det första/sista värdet i samlingen. Om samlingen är tom så skapas ett [runtime-fel](/grundlaggande/fel#runtime-fel-exceptions).

```csharp
List<int> myList = new List<int>() {4,3,2,1};

int i = myList.First(); // i blir 4
```

#### FirstOrDefault() / LastOrDefault()

Fungerar som First/Last, utom att metoden returnerar null, eller ett default-värde (t.ex. 0 för ints) ifall samlingen är tom.

```csharp
List<int> myList = new List<int>();
int i = myList.FirstOrDefault(); // i blir 0
```

### OrderBy()

Tar emot en delegate eller ett Lambda-uttryck som parameter, och använder den för att sortera samlingen. Delegaten tar emot ett föremål, och returnerar det värde som ska avgöra föremålens sortering.

OrderBy returnerar en Enumerable som innehåller samma föremål som originalsamlingen, sorterade i rätt ordning.

```csharp
List<Character> sortedCharacters = 
  characters.OrderBy(c => c.name)
  .ToList();
```

### Select

Tar emot en delegate eller ett Lambda-uttryck som parameter, och bygger en ny samling med det som returneras från delegaten/uttrycket för varje föremål i originalsamlingen.

Anges bara en parameter i delegaten/uttrycket så ska denna vara samma datatyp som originalsamlingens typparameter.

```csharp
List<int> intList = new() { 1, 2, 3, 4, 5 };

List<int> higherIntList = 
  intList.Select(x => x + 6)
  .ToList(); // 7,8,9,10,11
```

Skapa en lista med instanser av Character, där varje Characters konstruktor tar emot en string i form av ett namn (n):

```csharp
string[] names = {"Björn", "Mira", "Mohammad", "Kim"};

List<Character> characters = 
  names.Select(n => new Character(n))
  .ToList();
```

Skapa en lista med instanser av Character, där varje Characters konstruktor tar emot en string i form av ett namn (n) samt en siffra som är namnets index plus 1:

```csharp
string[] names = {"Björn", "Mira", "Mohammad", "Kim"};

List<Character> characters = 
  names.Select((n, i) => new Character(n, i+1))
  .ToList();
```

### Boolska

#### All()

Tar emot ett kriterium i form av en delegat eller ett Lambda-uttryck, och returnerar true ifall samtliga föremål i samlingen stämmer in på kriteriet.

```csharp
List<int> intList = new() { 1, 2, 3, 4, 5 };

bool allHigh = intList.All(n => n > 3); // false, för alla är inte > 3
```

#### Any()

Tar emot ett kriterium i form av en delegat eller ett Lambda-uttryck, och returnerar true ifall minst ett föremål i samlingen stämmer in på kriteriet.

```csharp
List<int> intList = new() { 1, 2, 3, 4, 5 };

bool hasHigh = intList.Any(n => n > 3); // true, för minst en är > 3
```

### Matematiska

Dessa fungerar bara för samlingar med tal – ints, doubles, floats och så vidare.

#### Max()

Returnerar det högsta värdet i samlingen.

```csharp
List<int> intList = new() { 2, 67, 23, 100, 1 };

int highest = intList.Max(); // 100
```

#### Min()

Returnerar det lägsta värdet i samlingen.

```csharp
List<int> intList = new() { 2, 67, 23, 100, 1 };

int lowest = intList.Min(); // 1
```

#### Average()

Returnerar medelvärdet av alla värden i samlingen, som en [double](/grundlaggande/datatyper#double).

```csharp
List<int> intList = new() { 2, 67, 23, 100, 1 };

double avg = intList.Average(); // 38.6
```


# Linq-queries

Linq queries är databasfrågor som fungerar likadant oavsett om man kör dem mot en databas eller vilken [samling ](/klasser-och-objektorientering/generiska-klasser#samlingar)som helst.

```csharp
List<Character> characters = new()
{
  new Character() {Name="Linda"},
  new Character() {Name="Micke"},
  new Character() {Name="Mira"},
  new Character() {Name="Pontus"},
  new Character() {Name="George"},
};

var shortNames =
            from c in characters
            where c.Name.Length < 6
            orderby c.Name
            select c;
            // Samlingen shortNames innehåller karaktärerna Micke, Mira och Linda,
            // sorterade i bokstavsordning efter namn.
```

Det finns en hel del man kan göra med Linq, men oftast klarar man sig med **from**, **in**, **where**, **orderby** och **select**.

## From…in

From och in anger tillsammans *varifrån* datan ska hämtas, och vilken variabel varje rad tillfälligt ska lagras i. Först skrivs from, därefter namnet på en variabel (som inte behlver skapas innan eller ger datatyp), därefter in och slutligen datakällan.

```csharp
var shortNames = from c in characters
            select c;
```

## Where

Where anger ett villkor som fungerar som ett filter – bara de föremål i samlingen (eller rader i tabellen) som matchar kriteriet får vara med i resultatet.

```csharp
var user = from c in characters
           where c.Name == "Micke" && c.Password == "12345"
           select c;
```

## Orderby

Orderby avgör hur resultaten *sorteras*.

```csharp
var shortNames =
            from c in characters
            where c.Name.Length < 6
            orderby c.Age
            select c;
            // Samlingen shortNames innehåller karaktärerna Micke, Mira och Linda,
            // sorterade efter ålder.
```

## Select

Select avgör *vad som läggs in* i resultatsamlingen.

```csharp
var shortNames =
            from c in characters
            where c.Name.Length < 6
            orderby c.Name
            select c.Name;
            // shortNames blir en string-samling med karaktärernas namn
```


# Databaser

När det gäller att lagra stora mängder data så används nästan alltid någon form av specialiserad mjukvara för detta. Ett vanligt exempel är MySQL, som körs som ett helt eget databas-serverprogram som olika programmeringsspråk sedan kan kontakta. Ett mer lättanvänt exempel är SQLite, där databaserna är relativt enkla textfiler som kan läsas av genom enkla anrop till ett SQLite-bibliotek. Ingen servermjukvara behöver köras på datorn.

SQL står för Structured Query Language, och alla SQL-språk brukar använda liknande språk. SQLite stöder färre SQL-kommandon än MySQL, men man kan ändå göra det mesta. Se [SQLite-kommandon](/annat/databaser/sqlite-kommandon) för dokumentation

Det finns extensions för Visual Studio Code som gör att man kan [jobba med SQLite-databaser](/annat/databaser/sqlite-och-vscode) utan att skriva C#-kod. Det är praktiskt för att skapa tabeller och förbereda databaser.

Slutligen finns [C#-bibliotek man kan installera via NuGet Gallery](/annat/databaser/c-och-sqlite) för att köra SQL-kommandon mot en specifik SQLite-databas.

## Databas

En traditionell relationell databas består av ett antal tabeller. Varje tabell beskriver en kategori av saker. Det som gör databasen relationell är kopplingarna mellan tabellerna. Om man t.ex. har en tabell med användare, och en tabell med artiklar som användarna skrivit, så lagrar man inte användarnamnet etc för respektive användare i artikel-tabellen. Istället lagrar man användarens unika ID.

### Tabeller

En tabell innehåller data om en kategori av "saker" – man kan till exempel ha en tabell för användare, eller en tabell för highscores. En tabell består av ett antal kolumner och rader.

### Kolumner

Varje kolumn i en tabell beskriver någon egenskap hos de saker som tabellen beskriver. T.ex. kan en kolumn innehålla förnamn, efternamn, användarnamn, lösenord, etc. Varje kolumn ska helst bara innehålla EN kategori av värden, så att varje cell i tabellen i sin tur bara innehåller ETT värde.

### Rader

Varje rad i en tabell beskriver en "sak", till exempel en användare, en artikel, ett highscore eller ett datorspel. Rader kan också kallas **entries**.

### Primärnycklar

För att kunna identifiera en specifik entry i en tabell, behöver man vara säker på att det finns något unikt med varje rad. Den delen som är unik brukar kallas "primärnyckel". I teorin kan vilken kolumn eller kombination av kolumner som helst vara primärnyckel, men i de allra flesta fall ges bara varje entry ett unikt nummer, ett ID, som deklareras som primärnyckel.

### Relation

Ifall man har en tabell vars information behöver refereras i en annan tabell, så säger man att de två tabellerna har en *relation*. Den enklaste formen av relation är en-till-många. Till exempel: En användare kan tillhöra en grupp, men en grupp kan innehålla många användare. Då kan man ha en tabell för grupper och en för användare, och så har man en kolumn i användar-tabellen som beskriver vilken grupp den användaren tillhör – där lagras grupptabellens primärnyckel.

### Normalisering

Normalisering kallas det när man följer ett antal regler designade att göra databasen så lätt att använda som möjligt. Till exempel försöker man att se till så att ingen data finns lagrad på flera ställen.

## CRUD

CRUD – Create, Read, Update och Delete – är de fyra operationer man brukar behöva göra med information som lagras i en databas.

### Create

Lägga till nya saker i en tabell, t.ex. nya användare.

### Read

Läsa av informationen om en sak i en tabell, t.ex. läsa av en användares användarnamn och lösenord för att kolla av mot inloggningsuppgifter.

### Update

Ändra en sak i en tabell, t.ex. byta en användares mailadress.

### Delete

Ta bort en sak ur en tabell, t.ex. ta bort en artikel.


# SQLite-kommandon

## CREATE TABLE

Skapar en tabell.&#x20;

```sql
CREATE TABLE users (
	id INTEGER PRIMARY KEY AUTOINCREMENT,
	name TEXT NOT NULL,
	password TEXT NOT NULL,
	email TEXT NOT NULL
);
```

Ovanstående skapar tabellen **users** med kolumnerna **id**, **name**, **password** och **email**.

* **INTEGER** betyder att kolumnen bara kan innehålla siffror, på samma sätt som en integer-variabel i C#..
* **TEXT** betyder att kolumnen bara kan innehålla text, lite som en string.
* **PRIMARY KEY** betyder att det är värdet i den kolumnen som är unikt och används för att identifiera varje rad.
* **AUTOINCREMENT** betyder att om man lägger till en rad i tabellen utan att ange ett värde för denna kolumn så ges den ett automatiskt nytt värde.
* **NOT NULL** betyder att man inte får lämna kolumnen tom.

| id🔑 | name | password | email |
| ---- | ---- | -------- | ----- |
|      |      |          |       |

## DROP TABLE

Raderar en tabell.

```
DROP TABLE users;
```

## ALTER TABLE

Gör ändringar i en existerande tabell

### RENAME

Byter namn på tabellen.

```sql
ALTER TABLE users
RENAME TO students;
```

### ADD COLUMN

Lägger till en ny kolumn

```
ALTER TABLE users
ADD COLUMN twitter_handle TEXT;
```

### DROP COLUMN

Tar bort en kolumn (och all data som finns i den). Fungerar inte för alla kolumner – till exempel kan man inte ta bort de som är primärnycklar.

```
ALTER TABLE users
DROP COLUMN twitter_handle;
```

### RENAME COLUMN

Byter namn på en kolumn

```sql
ALTER TABLE users
RENAME COLUMN name TO username;
```

## INSERT INTO

Lägger till en rad i en tabell.

```sql
INSERT INTO users (name,password,email)
VALUES('Mikael Bergström','12345','fake@bullshit.com');
```

Ovanstående stoppar in en rad i tabellen **users**.

* **(name,password,email)** betyder att det är de tre kolumnerna som värden ska stoppas in i.
* **VALUES('Mikael Bergström','12345','<fake@bullshit.com>')** betyder att texten "Mikael Bergström" läggs in i den första angivna kolumnen (name), "12345" läggs in i den andra kolumnen (password) och att "<fake@bullshit.com>" läggs in i den tredje (email).

En av tabellens fyra kolumner, "id", anges inte och får inget värde. Eftersom den är AUTOINCREMENT får den ändå ett värde, automatiskt.

| id🔑 | name             | password | email               |
| ---- | ---------------- | -------- | ------------------- |
| 1    | Mikael Bergström | 12345    | <fake@bullshit.com> |

Observera att man använder ' för att avgränsa texter (strings).&#x20;

## SELECT

Hämtar data från en tabell

```sql
SELECT * FROM users;
```

Ovanstående hämtar alla rader och alla kolumner från tabellen.

| id🔑 | name             | password | email                        |
| ---- | ---------------- | -------- | ---------------------------- |
| 1    | Mikael Bergström | 12345    | <fake@bullshit.com>          |
| 2    | Jacob Marley     | money$   | <moneyman@scroogemarley.com> |

```sql
SELECT name,email FROM users;
```

Ovanstående hämtar alla rader, men bara kolumnerna **name** och **email**.

| name             | email                        |
| ---------------- | ---------------------------- |
| Mikael Bergström | <fake@bullshit.com>          |
| Jacob Marley     | <moneyman@scroogemarley.com> |

### AS

Gör att kolumner kan ges nya namn i resultatet.

```sql
SELECT name AS namn FROM users;
```

| namn             |
| ---------------- |
| Mikael Bergström |
| Jacob Marley     |

### WHERE

Gör att man kan vara mer specifik med vilken eller vilka rader man vill läsa av.

```sql
SELECT name,email FROM users WHERE id=1;
```

Ovanstående hämtar bara kolumnerna name och email, och bara de rader där kolumnen id har värdet 0.

| name             | email               |
| ---------------- | ------------------- |
| Mikael Bergström | <fake@bullshit.com> |

### AND

Gör att man kan sätta ihop flera olika kriterier i en WHERE.

```
SELECT name FROM users WHERE email='fake@bullshit.com' AND password='12345';
```

### COUNT

Räknar antalet rader som innehåller ett värde.

```sql
SELECT COUNT(*) FROM users WHERE id=0;
```

## DELETE

Tar bort en eller flera rader från en tabell, baserat på ett eller flera kriterier.

```sql
DELETE FROM users WHERE id=0;
```

Kriterierna anges via WHERE, precis som för SELECT.

## UPDATE

Ändrar information i en eller flera celler, baserat på ett eller flera kriterier.

```sql
UPDATE users
SET email = 'deep@fake.com'
WHERE id=0;
```

Ovanstående kod ändrar email-kolumnens data till "<deep@fake.com>" för alla rader där id-kolumnen innehåller en nolla.

| id🔑 | name             | password | email                        |
| ---- | ---------------- | -------- | ---------------------------- |
| 0    | Mikael Bergström | 12345    | <deep@fake.com>              |
| 1    | Jacob Marley     | money$   | <moneyman@scroogemarley.com> |

## Avancerat: Relationer

En viktig funktion i *relationella databaser*, som MySQL eller SQLite, är *relationer*. Relationer är ett sätt att slippa dubletter av data. Ett exempel kan vara en databas där man håller reda på elever och klasser. För varje elev ska databasen hålla reda på förnamn, efternamn och personnummer. För varje klass ska databasen hålla reda på klassens namn och vilken lärare som är klassens mentor.

Dessutom behöver databasen hålla reda på *vilken elev som går i vilken klass*. Var lagras den informationen? Ett sätt vore att ha allting i en enda jättetabell:

**students**

| id🔑 | name       | surname   | pnumber     | classname | mentor           |
| ---- | ---------- | --------- | ----------- | --------- | ---------------- |
| 0    | Mikael     | Bergström | XXXXXX-XXXX | TE00A     | Mira Belle       |
| 1    | Mohammad   | Mohammadi | XXXXXX-XXXX | TE00B     | Kevin McAllister |
| 2    | Anna-Karin | Karlsson  | XXXXXX-XXXX | TE00A     | Mira Belle       |

Nackdelen blir att vi får dubletter – klassnamnen och mentorernas namn står dubbelt! För att undvika detta skapar man generellt istället två olika tabeller – en för elever och en för klasser – som har en *relation*.

**students**

| id🔑 | name       | surname   | pnumber     | classid |
| ---- | ---------- | --------- | ----------- | ------- |
| 1    | Mikael     | Bergström | XXXXXX-XXXX | 1       |
| 2    | Mohammad   | Mohammadi | XXXXXX-XXXX | 2       |
| 3    | Anna-Karin | Karlsson  | XXXXXX-XXXX | 1       |

**classes**

| id🔑 | name  | mentor           |
| ---- | ----- | ---------------- |
| 1    | TE00A | Mira Belle       |
| 2    | TE00B | Kevin McAllister |

Här är relationen att kolumnen **classid** i tabellen **students** innehåller siffror som hör ihop med kolumnen **id** i tabellen **classes**. Observera att det är classes-tabellens **primärnyckel** som används.

För att hindra användare från att lägga in icke-giltiga värden classid-kolumnen så kan relationen skrivas in i tabellens definition när den skapas (Det kan INTE göras i efterhand!):

```sql
CREATE TABLE classes (
	id INTEGER PRIMARY KEY AUTOINCREMENT,
	name TEXT NOT NULL,
	mentor TEXT NOT NULL
);

CREATE TABLE students (
	id INTEGER PRIMARY KEY AUTOINCREMENT,
	name TEXT NOT NULL,
	surname TEXT NOT NULL,
	pnumber TEXT NOT NULL,
	class_id INTEGER NOT NULL,
	FOREIGN KEY(class_id) REFERENCES classes(id)
);
```

Med andra ord lägger man helt enkelt till `FOREIGN KEY(x) REFERENCES table(y)` för att koppla kolumnen x till kolumnen y i tabellen "table"

## Avancerat: JOIN

Joins är ett sätt att sätta ihop tabeller som har en relation, när man efterfrågar data med SELECT.

<pre class="language-sql"><code class="lang-sql">SELECT students.name AS student_name, classes.name AS class
<strong>	FROM students
</strong>	INNER JOIN classes
<strong>	ON students.classid = classes.id;
</strong></code></pre>

Det finns flera sorters JOIN, men INNER JOIN är den vanligaste. Man anger först som vanligt vilka kolumner man vill ha med, sedan FROM en första tabell. Sedan lägger man till INNER JOIN en annan tabell, och så ON vilka kolumner som ska kopplas ihop.

| student\_name | class |
| ------------- | ----- |
| Mikael        | TE00A |
| Mohammad      | TE00B |
| Anna-Karin    | TE00A |

Observera att man alltså måste specifiera vilken tabell varje kolumn kommer från i första delen av SELECT-kommandot, framför allt när kolumner i båda tabellerna har samma namn.


# SQLite och VSCode

Visual Studio Code har inget inbyggt stöd för SQLite, men det finns såklart bra extensions:

* [SQLite](https://marketplace.visualstudio.com/items?itemName=alexcvzz.vscode-sqlite) - gör att man kan öppna och utföra kommandon/queries mot en SQLite-databas

## Öppna en databas

Högerklicka på en sqlite-fil eller en db-fil och välj "Open database".

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FkFjDZGMr5fsbSk9gxxIY%2Fimage.png?alt=media&amp;token=ddd15d51-55e3-4df1-9544-6b3fbc595fc6" alt=""><figcaption></figcaption></figure>

Man kan också "öppna" tomma filer som SQLite-databaser – genom att sedan köra [CREATE TABLE](/annat/databaser/sqlite-kommandon#create-table) så görs den tomma filen till en databas.

När databasen är öppnad bör det dyka upp en "SQLite Explorer"-flik:

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2FHaQN7X7qCXxroDuzxDiU%2Fimage.png?alt=media&amp;token=2a377b99-1df5-4a89-ba73-856561061165" alt=""><figcaption></figcaption></figure>

Databasen i exemplet ovan innehåller en tabell som heter users, som i sin tur har kolumnerna id och name.

## Stäng en databas

Högerklicka på databasen i SQLite Explorer och välj "Close database".

## Köra ett kommando

Högerklicka på antingen databasen eller en av tabellerna i SQLite Explorer och välj "New query". För tabellen kan man välja mellan två färdigifyllda query-mallar: en för [INSERT INTO](/annat/databaser/sqlite-kommandon#insert-into) och en för [SELECT](/annat/databaser/sqlite-kommandon#select).

Det du får är en ny textfil som innehåller antingen ett tomt utrymme där du kan skriva en query, eller en ny textfil med förifyllda kommandon du kan redigera.

<figure><img src="https://3459450691-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MHmNgpRz-b16wpwGwZI-887967055%2Fuploads%2Fm7pJJJmU4aMJ3rOjuci1%2Fimage.png?alt=media&amp;token=22123089-6f27-439f-83a7-e50c544eeb02" alt=""><figcaption></figcaption></figure>

För att köra queryn, tryck på F1 och kör "SQLite: Run Query". Om det du körde var en SELECT-query bör resultatet nu dyka upp i ett sidofönster.

## Skapa en databas

Skapa en tom fil, som du döper till något som slutar med .sqlite, t.ex. "database.sqlite".

Öppna filen som en databas, enligt ovan.

Högerklicka på databasen i SQLite, välj "New Query".

Lägg till en tabell genom att skriva in kommandot för CREATE TABLE.

Tryck F1 och välj "SQLite: Run Query".

## Titta på en tabell

Se till att databasen är öppnad.

Högerklicka på tabellen i SQLite Explorer, välj "Show Table".


# C# och SQLite

Börja med att lägga till NuGet-paketet **Microsoft.Data.Sqlite**. Antingen genom att använda NuGet Gallery eller genom att köra i konsolen:

```powershell
dotnet add package Microsoft.Data.Sqlite
```

## SqliteConnection

En SqliteConnection är ett objekt som är kopplat till en SQLite-databasfil.

```csharp
SqliteConnection connection = new SqliteConnection("Data Source=users.sqlite")
connection.Open();
```

Det är ofta en bra idé att använda ett [using-kodblock](/filhantering/open-close-using#using) för att säkerställa att programmet inte håller kvar kopplingen längre än nödvändigt. Då stängs kopplingen ner säkert i samband med att using.kodblocket avslutas.

```csharp
using (SqliteConnection connection = new SqliteConnection("Data Source=users.sqlite"))
{
  connection.Open();
  // Kod som använder kopplings-objektet
}
```

### CreateCommand()

Skapar ett nytt SqliteCommand-objekt. Se nedan.

```csharp
SqliteCommand command = connection.CreateCommand();
```

## SqliteCommand

Ett SqliteCommand är ett objekt som motsvarar ett [SQLite-kommando](/annat/databaser/sqlite-kommandon). Det har ett textinnehåll i form av själva kommandot, och kan köras på flera olika sätt. Ett SQLiteCommand är alltid kopplat till en SqliteConnection; kommandot skickas alltid till den SQLite-databasen.

### commandText

commandText är kommandotexten som ska köras mot databasen.

```csharp
command.CommandText =
  @"
    SELECT name
    FROM users
  ";
```

### ExecuteNonQuery()

Kör kommandot. Perfekt för t.ex kommandon som lägger in ny information i en tabell. Returnerar en integer som beskriver hur många rader som ändrats, tagits bort eller lagts till.

```csharp
SqliteCommand newUserCommand = connection.CreateCommand();
command.CommandText =
  @"
    INSERT INTO users (name,password,email)
    VALUES('Mikael Bergström','12345','fake@bullshit.com');
  ";

int rowsAffected = command.ExecuteNonQuery();
```

### ExecuteScalar()

Kör kommandot, och returnerar resultatet – men bara första cellen (första kolumnen i första raden). Resultatet returneras som ett object, som dessutom kan vara null ifall operationen inte returnerade något. Med andra ord behövs både [casting ](/grundlaggande/typkonvertering#casting)och något sätt att hantera nullvärden t.ex. via [null-coalescing](/grundlaggande/operatorer#null-coalescing).

```csharp
SqliteCommand countCommand = connection.CreateCommand();

countCommand.CommandText =
@"
  SELECT COUNT(*)
  FROM users
";

long result = 0;
object resultObj = countCommand.ExecuteScalar() ?? 0;
result = (long)resultObj;
```

### ExecuteReader()

Kör kommandot, och returnerar en SQLiteDataReader för att läsa av resultatet. Passar bäst för SELECT-kommandon som returnerar flera rader och/eller kolumner.

```csharp
SqliteCommand selectCommand = connection.CreateCommand();

selectCommand.CommandText =
@"
  SELECT (name)
  FROM users
";

using (SqliteDataReader reader = selectCommand.ExecuteReader())
{
  // kod för att läsa datan
}
```

## SqliteDataReader

Ett SqliteDataReader-objekt används för att läsa av ett resultat från en SQL-operation (ofta ett SELECT-kommando), en rad i taget.

Precis som med SqliteConnection-objekt använder man oftast ett [using-block](/filhantering/open-close-using#using) för att se till så att reader-objektet tas bort ordentligt när man är klar med det.

### Read()

Flyttar readerns "läshuvud" till nästa rad, om den finns. Om den inte finns, returneras true.

```csharp
while (reader.Read())
{
  // Kod för att läsa radens data
}
```

### Get?()

Det finns många metoder som börjar med Get – till exempel GetString, GetInt32, GetFloat och GetBoolean. De tar alla emot en integer som parameter, och returnerar datan den nuvarande raden och den kolumn som anges av siffran. De försöker också konvertera (parse) datan till rätt datatyp.

```csharp
while (reader.Read())
{
  // Läser datan i den första kolumnen och tolkar den som en string
  string name = reader.GetString(0);
  
  Console.WriteLine(name);
}
```

### FieldCount

En property som talar om hur många fält (kolumner) resultatet innehåller.

### GetName()

Returnerar namnet på en specifik kolumn i resultatet.

```csharp
for (var i = 0; i < reader.FieldCount; i++)
{
  Console.WriteLine(reader.GetName(i));
}
```




---

[Next Page](/llms-full.txt/1)

