case (in anderen Sprachen oft als switch bezeichnet) ist eine Form von Kontrollausdruck, ähnlich wie if-else.
Mit case lassen sich mehrere if-else-if-Anweisungen verketten. Das kann lesbarer sein und ermöglicht mächtige Konstrukte.
Eine case-Anweisung wird durch das Schlüsselwort case eingeleitet, auf das ein optionaler Ausdruck folgt.
Für jeden Fall wird dann das Schlüsselwort when verwendet, gefolgt von einem Ausdruck, der mit dem Case-Ausdruck verglichen wird.
Das Schlüsselwort when sollte nicht gegenüber dem Schlüsselwort case eingerückt werden.
Nach dem Schlüsselwort when folgt der Code, der ausgeführt werden soll, wenn der Case-Ausdruck zum When-Ausdruck passt.
Case erlaubt eine optionale else-Anweisung, die ausgeführt wird, wenn kein anderer Fall passt.
Der Case-Ausdruck wird ausgewertet und dann mit jedem When-Ausdruck verglichen.
Der Vergleich erfolgt mit dem Subsumtionsoperator (===).
case 1
when 1
puts "One"
when 2
puts "Two"
else
puts "Other"
end
# => One
# This is the same as:
tmp = 1
if 1 === tmp
puts "One"
elsif 2 === tmp
puts "Two"
else
puts "Other"
end
===)Der Subsumtionsoperator (===) unterscheidet sich etwas vom Gleichheitsoperator (==).
Der Operator prüft, ob die rechte Seite ein Element der Menge ist, die die linke Seite beschreibt.
Das bedeutet, dass es eine Rolle spielt, wo die einzelnen Operanden stehen.
Wie das funktioniert, hängt vom Typ der linken Seite ab. Ein Range prüft zum Beispiel, ob die rechte Seite im Bereich liegt, und ein Object prüft, ob die rechte Seite eine Instanz des Object ist.
(1..3) == 1 # => false
(1..3) === 1 # => true
String == "foo" # => false
String === "foo" # => true
Cases ermöglichen es, mehrere Ausdrücke in einem einzigen Case abzugleichen, wobei die einzelnen möglichen Werte durch ein Komma getrennt werden. Der Code wird ausgeführt, wenn einer der Ausdrücke passt. Das kann bei einem einzelnen Case mit mehreren möglichen Werten nützlich sein.
case 1
when 1, 2
puts "One or two"
else
puts "Other"
end
Cases können auch prüfen, ob ein Wert in einem Bereich liegt. Dazu verwendest du einen Bereich als When-Ausdruck.
case var
when 1..3
puts "One to three"
else
puts "Other"
end
Wenn kein Case-Ausdruck benötigt wird, kannst du ihn weglassen. Dadurch wird jeder When-Ausdruck auf seinen Wahrheitswert geprüft. Und sie verhalten sich dann wie if-else-if-Anweisungen.
case
when 1 == 1
puts "One is equal to one"
when 1 > 2
puts "One is greater than two"
else
puts "Other"
end
Crystal erlaubt einzeilige Case-Anweisungen.
Das ist praktisch, wenn du eine einfache einzeilige Anweisung hast.
In der einzeiligen Form schreibst du die Anweisung als when <expression> then <statement>.
In der Else-Anweisung schreibst du sie als else <statement>.
case var
when 1 then puts "One"
when 2 then puts "Two"
else puts "Other"
end
Case ermöglicht den Abgleich mit Typen.
Der Vergleich verwendet den Operator is_a?, um den Typ der Variable zu prüfen.
So lässt sich zum Beispiel für jeden Typ in einem Union-Typ ein eigener Zweig anlegen.
case var
when Int32
puts "Int32"
when String
puts "String"
else
puts "Other"
end
Case erlaubt die Verwendung eines impliziten Objekts. So kann ein When-Ausdruck zum Beispiel ein Methodenaufruf auf dem Case-Ausdruck sein. Je nachdem, ob die Methode einen wahren oder falschen Wert zurückgibt, passt der Case oder nicht.
case 1
when .odd?
puts "Odd"
when .even?
puts "Even"
end
Case ermöglicht exhaustive Cases. Das bedeutet, dass du sicherstellen kannst, dass alle möglichen Werte behandelt werden.
Es ähnelt der When-Anweisung, verwendet aber das Schlüsselwort in statt when.
Ein exhaustiver Case unterstützt keine when- oder else-Anweisungen.
Exhaustive Cases können auf Bools, Union-Typen, Enum und Tuples angewendet werden.
Die beiden letztgenannten werden in späteren Konzepten behandelt.
Exhaustive Cases bedeuten, dass alle Möglichkeiten behandelt werden müssen. Andernfalls gibt es einen Kompilierfehler.
Union-Typen in einem exhaustiven Case zu behandeln, ähnelt einem nicht-exhaustiven Case.
var : (Int32 | String | Bool)
case var
in Int32
puts "Int32"
in String
puts "String"
in Bool
puts "Bool"
end
Bools lassen sich als exhaustiver Case behandeln, indem du die Schlüsselwörter true und false verwendest.
var : Bool
case var
in true
puts "True"
in false
puts "False"
end