Gå til indholdet

Mutable og Immutable typer

Når man arbejder med datatyper i programmering, er det vigtigt at forstå forskellen mellem mutable og immutable typer. Mutable typer er dem, hvis tilstand kan ændres efter deres oprettelse, mens immutable typer er dem, hvis tilstand ikke kan ændres efter deres oprettelse. Denne forskel er særlig vigtig i C#, hvor både værdi- og referencetyper kan være enten mutable eller immutable.

Information til undervisere

De studerende skal kende til begreberne “mutable og immutable typer”. Til at starte med på et overordnet plan. Brug Stringbuilder (mutable) og string (immutable) som eksempel.

Mutable Typer

Mutable typer tillader ændringer af deres værdier eller indhold efter deres oprettelse. For eksempel er klasser som List og StringBuilder mutable, hvilket betyder, at du kan ændre deres indhold ved hjælp af metoder som Add, Remove, Insert og Append. Dette giver fleksibilitet, men kan også potentielt føre til utilsigtede bivirkninger i din kode, hvis objekter ændres utilsigtet.

List<int> numbers = new List<int> { 1, 2, 3, 4 };
numbers.Add(5); // Tilføjer tallet 5 til listen
numbers.Remove(3); // Fjerner tallet 3 fra listen
numbers[1] = 10; // Ændrer det andet element (index 1) i listen til 10

StringBuilder sb = new StringBuilder("Hello, ");
sb.Append("world!"); // Tilføjer "world!" til StringBuilder
sb.Replace("world", "C#"); // Erstatter "world" med "C#"
string result = sb.ToString(); // Konverterer StringBuilder til en string: "Hello, C#!"

Immutable Typer

Immutable typer er dem, hvis tilstand ikke kan ændres efter deres oprettelse. Dette betyder, at når et objekt af en immutable type er oprettet, vil det altid beholde den samme værdi. Et eksempel på en immutable type i C# er string. Når du opretter en string, kan du ikke ændre dens indhold direkte. Alle operationer, der ser ud til at ændre en string, såsom at tilføje tegn eller erstatte delstrenge, returnerer faktisk et nyt string-objekt, mens det oprindelige objekt forbliver uændret. Dette gælder også for DateTime-strukturen, som også er immutable.

string originalString = "Hello, world!";
string upperString = originalString.ToUpper(); // Opretter en ny string med alle tegn i store bogstaver
string replacedString = originalString.Replace("world", "C#"); // Opretter en ny string, hvor "world" er erstattet med "C#"

DateTime originalDate = new DateTime(2023, 3, 25);
DateTime newDate = originalDate.AddDays(7); // Opretter en ny DateTime 7 dage efter originalDate
DateTime nextMonth = originalDate.AddMonths(1); // Opretter en ny DateTime 1 måned efter originalDate

using System.Collections.Immutable;

ImmutableList<int> originalList = ImmutableList.Create(1, 2, 3);
ImmutableList<int> newList = originalList.Add(4); // Opretter en ny ImmutableList med elementet 4 tilføjet

ImmutableDictionary<string, int> originalDict = ImmutableDictionary.Create<string, int>()
    .Add("Alice", 30)
    .Add("Bob", 25);
// Opretter en ny ImmutableDictionary, hvor værdien for nøglen "Alice" er ændret til 31
ImmutableDictionary<string, int> newDict = originalDict.SetItem("Alice", 31); 

Immutable typer har flere fordele, herunder:

  • De gør din kode lettere at forstå og forudsige, fordi deres værdier ikke ændres utilsigtet.
  • De er trådsikre, da flere tråde kan få adgang til det samme objekt uden risiko for at skabe konflikter eller inkonsistente tilstande.
  • De kan forbedre ydeevnen ved at reducere behovet for at oprette nye objekter og øge hastigheden for visse operationer, såsom strengkonkatenering ved hjælp af StringBuilder.

Når du designer dine egne klasser og strukturer i C#, er det vigtigt at overveje, om de skal være mutable eller immutable. Generelt bør du vælge immutability, når det er praktisk og giver mening for den type data, du arbejder med. Hvis dine data kræver ændringer og dynamisk adfærd, kan du vælge at bruge mutable typer, men du bør være opmærksom på mulige bivirkninger og sikkerhedsspørgsmål, der kan opstå.

Egne typer

Her er et eksempel på oprettelse af en mutable og immutable klasse:

MutablePerson person = new MutablePerson("Alice", 30);
person.Name = "Alicia"; // Ændrer navnet
person.Age = 31; // Ændrer alderen

public class MutablePerson
{
    public string Name { get; set; }
    public int Age { get; set; }

    public MutablePerson(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
ImmutablePerson person = new ImmutablePerson("Alice", 30);
// person.Name = "Alicia"; // Dette vil give en kompileringsfejl, fordi Name er skrivebeskyttet
// person.Age = 31; // Dette vil give en kompileringsfejl, fordi Age er skrivebeskyttet


public class ImmutablePerson
{
    public string Name { get; }
    public int Age { get; }

    public ImmutablePerson(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

Opgaver