semi-final switch?

Steven Schveighoffer schveiguy at gmail.com
Fri Jun 18 12:26:24 UTC 2021


On 6/18/21 12:40 AM, Mathias LANG wrote:
> On Thursday, 17 June 2021 at 21:41:28 UTC, Steven Schveighoffer wrote:
>> A final switch on an enum complains if you don't handle all the enum's 
>> cases. I like this feature.
>>
>> However, sometimes the data I'm switching on is coming from elsewhere 
>> (i.e. a user), and while I want to enforce that the data is valid 
>> (it's one of the enum values), I don't want to crash the program if 
>> the incoming value is not correct. But final switch doesn't let me 
>> declare a default case (to throw an exception instead).
>>
>> If I use a non-final switch, then my code might forget to handle one 
>> of the cases.
>>
>> Oh, and to throw a monkey wrench in here, the value is a string, not 
>> an integer. So I can't use std.conv.to to verify the enum is valid 
>> (plus, then I'm running a switch twice).
>>
>> Any ideas on better ways to handle this?
>>
> 
> Well, if you receive an `enum` that have an out of bounds value, your 
> problem lies in the caller, not the callee. You're breaking the most 
> fundamental promise of a type, that is, the values it can take. And you 
> obviously also break any `@safe` function by feeding it this value.

Yeah, I know. But I'm not receiving an enum. I'm receiving a string. But 
I want to handle a certain set of those strings everywhere. So what I 
tried is to make an enum that has those strings. Then I would use final 
switches whenever I handle it, so if I add a new string to the list, the 
compiler will tell me where I missed handling that new one.

> 
> So instead of thinking in terms of `enum`, I would say, think in them of 
> the value, and generate the switch:
> ```D
> SWITCH: switch (myRawValue)
> {
>      static foreach (EV; NoDuplicates!(EnumMembers!MyEnum))
>      {
>          case EV:
>              // Handle;
>              break SWITCH;
>      }
>      default:
>          throw new Exception("Invalid value: " ~ myRawValue);
> }
> ```
> 

The // Handle then becomes a new switch. Though maybe I can group some 
of them together.

I may as well use std.conv.to at that point.

I think that's what I'm probably going to do, I just wondered if there 
was a better way.

-Steve


More information about the Digitalmars-d-learn mailing list