On Saturday, 12 April 2014 at 13:33:07 UTC, Jonathan M Davis
wrote:
On further reflection, I think that having enum and final enum
would make
sense as long as enum were changed so that it introduced an
alias rather than
a new type. A new type just doesn't make sense if you're not
listing all the
values - especially because the few protections that the
compiler has against
giving an enum a non-enumerated value just get in the way of
that use case -
whereas if the enum _is_ intended to enumerate all its values,
it makes sense
that it would introduce a new type that was protected against
having it set to
non-enumerated values. So,
enum UserID : ulong { nobody, expired = ulong.max }
would then introduce an alias UserID for ulong as well as
namespace the
constants nobody and expired, but there would be no new type
introduced, so it
would not protect against being assigned non-enumerated values,
and it would
not affect overloading. It also wouldn't work with final switch.
final enum State { initial, waiting, running, done }
would then be the same as
enum State { initial, waiting, running, done }
is now except that the compiler would actually guarantee that
no variable of
type State could have a non-enumerated value unless a cast was
used (so any
operation which wasn't guaranteed to result in an enumerated
value would
result in a value of the base type rather than the enum type).
And of course,
it would then work properly with final switch, because it
couldn't have a non-
enumerated value unless you forced it with a cast.
With that separation, we can then separate out the enums which
are really
enumerations and those which are really just a group of related
constants. But
I think that the key thing is that introducing a new type
really doesn't make
sense if it's just a group of related constants. Introducing an
alias is fine
- but a new type just doesn't make sense IMHO.
For better or worse, if we went this route, we'd end up with
something closer
to C++11's enums and enum classes, though unlike enum classes,
our final enum
would implicitly convert to its base type, and operations on it
which weren't
guaranteed to result in a valid enum value would result in the
base type,
whereas it's my understanding that you have to overload
operators to get any
of that working at all with enum classes.
- Jonathan M Davis
If we were really serious about changing enums, I'd say scrap the
whole thing and take a look at how Rust does them, and change the
semantics of final switch to allow for pattern matching, while
leaving switch around as a legacy C construct and discouraging
its use in regular code.