Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between switch cases "@unknown default" and "default" in Swift 5

Tags:

swift

swift5

From Swift 5, new case attribute @unknown is introduced.

What is the exact difference when @unknown is being used and not being used? In which case we have to use @unknown keyword?

like image 227
Saranjith Avatar asked Mar 29 '19 06:03

Saranjith


People also ask

What does @unknown mean in Swift?

@unknown default case In Swift 5.0, a new @unknown keyword can be added to the default switch case. This doesn't change the behavior of default , so this case will still match any cases that aren't handled in the rest of the switch block.

What is the use of fallthrough in Swift?

If you want your switch statement fall through or you want C style fallthrough feature then you can use fallthrough statement. This statement is used to forcefully execute the case present next after the matched statement even though the case is not matching the specified condition.

What is Fallthrough in switch statement Swift?

The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C's standard switch statement behaviour.

What is @frozen in Swift?

Introduced with Swift 5, the @unknown attribute is particularly useful when switching over a nonfrozen enumeration. While the @frozen attribute is used on familiar enums such as Result or Optional within the standard library..


1 Answers

From SE-0192: Handling Future Enum Cases (emphasis mine):

When switching over a non-frozen enum, the switch statement that matches against it must include a catch-all case (usually default or an "ignore" _ pattern).

switch excuse { case .eatenByPet:   // … case .thoughtItWasDueNextWeek:   // … } 

Failure to do so will produce a warning in Swift 5. A program will trap at run time if an unknown enum case is actually encountered.

All other uses of enums (if case, creation, accessing members, etc) do not change. Only the exhaustiveness checking of switches is affected by the frozen/non-frozen distinction. Non-exhaustive switches over frozen enums (and boolean values) will continue to be invalid in all language modes.

Here's a more complicated example:

switch (excuse, notifiedTeacherBeforeDeadline) { case (.eatenByPet, true):   // … case (.thoughtItWasDueNextWeek, true):   // … case (_, false):   // … } 

This switch handles all known patterns, but still doesn't account for the possibility of a new enum case when the second tuple element is true. This should result in a warning in Swift 5, like the first example.

@unknown

The downside of using a default case is that the compiler can no longer alert a developer that a particular enum has elements that aren't explicitly handled in the switch. To remedy this, switch cases will gain a new attribute, @unknown.

switch excuse { case .eatenByPet:   // … case .thoughtItWasDueNextWeek:   // … @unknown default:   // … } 

Like the regular default, @unknown default matches any value; it is a "catch-all" case. However, the compiler will produce a warning if all known elements of the enum have not already been matched. This is a warning rather than an error so that adding new elements to the enum remains a source-compatible change. (This is also why @unknown default matches any value rather than just those not seen at compile-time.)

@unknown may only be applied to default or a case consisting of the single pattern _. Even in the latter case, @unknown must be used with the last case in a switch. This restriction is discussed further in the "unknown patterns" section under "Future directions".

The compiler will warn if all enums in the pattern being matched by @unknown are explicitly annotated as frozen, or if there are no enums in the pattern at all. This is a warning rather than an error so that annotating an enum as frozen remains a source-compatible change. If the pattern contains any enums that are implicitly frozen (i.e. because it is a user-defined Swift enum), @unknown is permitted, in order to make it easier to adapt to newly-added cases.

@unknown has a downside that it is not testable, since there is no way to create an enum value that does not match any known cases, and there wouldn't be a safe way to use it if there was one. However, combining @unknown with other cases using fallthrough can get the effect of following another case's behavior while still getting compiler warnings for new cases.

switch excuse { case .eatenByPet:   showCutePicturesOfPet()  case .thoughtItWasDueNextWeek:   fallthrough @unknown default:   askForDueDateExtension() } 
like image 111
Hitesh Surani Avatar answered Oct 07 '22 16:10

Hitesh Surani