On Saturday, 13 October 2012 at 20:25:56 UTC, Jonathan M Davis
wrote:
MyEnum me;
final switch (me) // no init case necessary nor allowed
{
case MyEnum.first: break;
case MyEnum.second: break;
}
}
Think about that for a moment. What happens when that final
switch statement is actually run?
There's a bug in that code, because MyEnum default-initializes to
an invalid value. It's effectively the same as this following
code, where the programmer has failed to initialize MyEnum
variable with a valid value:
enum MyEnum { first, second }
void main()
{
MyEnum me = cast(MyEnum)(-123);
final switch (me)
{
case MyEnum.first: break;
case MyEnum.second: break;
}
}
I think that the final switch statement above should throw an
unrecoverable error. I tested it, and nothing happens. I strongly
disagree with this behavior of the compiler (a bug perhaps?).
And remember, that in many cases, T.init is considered to be
perfectly valid. By allowing a final switch _not_ to have it,
it then becomes easy to forget to add a case for it when you
_need_ to, completely defeating the purpose of the final
switch (to make it so that both you and the compiler know that
all of the possible values are accounted for).
If T.init is considered to be perfectly valid, then it means,
that a synonym for it exists among the enumerations. E.g:
enum MyEnum { init = 1, first = 1, second = 42 }
enum ThyEnum { first, second }
In both of those cases, T.first is the synonym of T.init, which
is what both of those enums default-initialize to. Therefore, if
T.init is a valid value, and thus has a synonym among the
enumerations of T, then you can't add a case for init in a final
switch:
MyEnum me;
final switch (me)
{
MyEnum.first: break;
MyEnum.second: break;
MyEnum.init: // Error: duplicate case cast(MyEnum)1
// in switch statement
}
So, this situation you describe, where you *need* to add a case
for init in a final switch, it doesn't exist. T.init should
always either 1) have a synonym among the enumerations or 2)
represent an invalid value.