Overskrivning af operatorer
Der kan være situationer, hvor du ønsker at kunne sammenligne to objekter af klasser på forskellige måder Umiddelbart giver C# kun mulighed for at kontrollere, om referencen er det samme. Med udgangspunkt i følgende klasse:
kan objekter sammenlignes som følger:
Person p1 = new Person
{
Navn = "Mathias",
Alder = 14,
};
Person p2 = new Person
{
Navn = "Mathias",
Alder = 14,
};
Console.WriteLine(p1 == p2); // false
Selv om to objekter indeholder samme værdier, så vil en sammenligning fejle, fordi det er referencerne, der sammenlignes og ikke værdierne. Men det kan du ændre, hvis du ønsker, og du kan endda lade Visual Studio eller Visual Studio Code gøre det for dig.
Hvis du placerer cursoren på klassenavnet, vil du få mulighed for at få hjælp til at overskrive operatorer ved at vælge ”Generate Equals and GetHashCode…”. Det vil skabe denne dialogboks:
Et klik på OK-knappen vil ændre koden i Person-klassen til følgende:
class Person : IEquatable<Person?>
{
public string Navn { get; set; }
public int Alder { get; set; }
public override bool Equals(object? obj)
{
return Equals(obj as Person);
}
public bool Equals(Person? other)
{
return other != null &&
Navn == other.Navn &&
Alder == other.Alder;
}
public override int GetHashCode()
{
return HashCode.Combine(Navn, Alder);
}
public static bool operator ==(Person? left, Person? right)
{
return EqualityComparer<Person>.Default.Equals(left, right);
}
public static bool operator !=(Person? left, Person? right)
{
return !(left == right);
}
}
Overskrivning af == og !=
Der tilføjes nu både en overskrivning af == og != operatorerne samt en overskrivning af metoderne Equals (som internt bruges til at sammenligne) og GetHashCode (som benyttes til at skabe en unik nøgle, der benyttes internt af runtime i eksempelvis samlinger af objekter). Det ligger uden for denne bogs rammer at komme nærmere ind på den autogenererede kode, men resultatet er meget tydeligt:
Person p1 = new Person
{
Navn = "Mathias",
Alder = 14,
};
Person p2 = new Person
{
Navn = "Mathias",
Alder = 14,
};
Console.WriteLine(p1 == p2); // true
Nu sammenlignes på værdier og ikke på referencer, hvilket nogle gange kan være ret praktisk.
Overskrivning af > og <
På samme måde kan du også vælge at overskrive eksempelvis < (mindre end) og > (større end) operatorerne. Det kunne være, at du ville have en forretningslogik, hvor det gav mening at sammenligne objekter på den måde. Her er eksempelvis en simpel terning:
class Terning
{
public int Værdi { get; private set; }
private Random random = new Random();
public Terning()
{
Ryst();
}
public void Ryst()
{
Værdi = random.Next(1, 7);
}
}
Og her er brugen af klassen med et par terninger:
Terning t1 = new Terning();
Console.WriteLine(t1.Værdi); // Tilfældig værdi
Terning t2 = new Terning();
Console.WriteLine(t2.Værdi); // Tilfældig værdi
Det kunne måske være smart, at kunne spørge om t1 > t2 eller omvendt, men det er jo kun dig, der ved, hvordan logikken skal være, og det kan du fortælle runtime ved at overskrive de to operatorer:
class Terning
{
public int Værdi { get; private set; }
private Random random = new Random();
public Terning()
{
Ryst();
}
public void Ryst()
{
Værdi = random.Next(1, 7);
}
public static bool operator >(Terning? left, Terning? right)
{
return left.Værdi > right.Værdi;
}
public static bool operator <(Terning? left, Terning? right)
{
return left.Værdi < right.Værdi;
}
}
Da klassen Terning ved hvordan instanser skal sammenlignes er følgende kode mulig:
Terning t1 = new Terning();
Terning t2 = new Terning();
bool mindre = t1 < t2;
bool større = t1 > t2;
Du kan naturligvis også vælge at overskrive andre operatorer – herunder == og != som før nævnt.