WORDS
C# 7: Mönstermatchning med is och switch
C# är ett programmeringsspråk som kontinuerligt tar beprövade idéer från andra språk. En sådan idé är mönstermatchning (eng. pattern matching) från funktionella programmeringsspråk. Det är ett alternativ till objektorienteringens arv, där man med hjälp av virtual och override väljer implementation baserat på objektets typ. Genom hela artikeln kommer vi använda areaberäkning som exempel.
Exempel: beräkna area
Låt säga att vi har ett par olika sorts former, rektanglar och cirklar, och vill beräkna deras areor. Givet en äldre version av C#, skulle implementationen skulle kunna se ut såhär.
public static double ComputeArea(object shape)
{
if (shape is Rectangle)
{
var r = (Rectangle)shape;
return r.Length * r.Height;
}
else if (shape is Circle)
{
var c = (Circle)shape;
return c.Radius * c.Radius * Math.PI;
}
else if (shape is Triangle)
{
var t = (Triangle)shape;
return t.Base * t.Height / 2;
}
throw new ArgumentException("Unknown shape");
}
Deklarera variabler med is
Numera kan man deklarera en variabel direkt i is-uttrycket, så det finns ingen anledning att cast:a inputen.
public static double ComputeArea2(object shape)
{
if (shape is Rectangle r)
return r.Length * r.Height;
else if (shape is Circle c)
return c.Radius * c.Radius * Math.PI;
else if (shape is Triangle t)
return t.Base * t.Height / 2;
throw new ArgumentException("Unknown shape");
}
switch med typer
Man har historiskt bara kunnat använda switch med konstanta mönster, men nu kan man också matcha mot typer.
public static double ComputeArea3(object shape)
{
switch (shape)
{
case Rectangle r:
return r.Length * r.Height;
case Circle c:
return c.Radius * c.Radius * Math.PI;
case Triangle t:
return t.Base * t.Height / 2;
default:
throw new ArgumentException("Unknown shape");
}
}
switch med when
I C# 7.0 har man utökat switch till att bli så flexibel, att den kan ersätta många if-else if-else-kedjor.
public static double ComputeArea4(object shape)
{
switch (shape)
{
case Rectangle r when r.Length == 0 || r.Height == 0:
case Circle c when c.Radius == 0:
case Triangle t when t.Base == 0 || t.Height == 0:
return 0;
case Rectangle r:
return r.Length * r.Height;
case Circle c:
return c.Radius * c.Radius * Math.PI;
case Triangle t:
return t.Base * t.Height / 2;
default:
throw new ArgumentException("Unknown shape");
}
}
Vidare läsning
Microsofts dokumentation om mönstermatchning går in i detalj i hur kompilatorn tolkar olika användningar.