Comparison of Enumerations with base type of String?

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Aug 26 21:52:56 PDT 2017


On Sunday, August 27, 2017 03:47:58 Michael Reiland via Digitalmars-d-learn 
wrote:
> You can randomly assign a string to an enum?  Or am I
> misunderstanding that last bit of code?

No, you can't directly assign a string to an enum of type string. That's
part of why they don't pass isInputRange. This code fails to compile

    enum S : string
    {
        a = "foo",
        b = "bar"
    }

    void main()
    {
        S s = "baz";
    }

though you can force it with a cast, e.g.

    S s = cast(S)"baz";

Unfortunately however, enums in D really aren't very strongly typed. So,
while direct assignment will fail, stuff like

    S s = S.a;
    s ~= "blah";

will compile. And enums of base type int have the same problem - e.g.

    E e = E.a | E.b;

In both cases, you trivially end up with a value that is not valid for that
enum type and will likely cause problems with final switch (which will
result in an Error being thrown when not compiling with -release but will do
who-knows-what when -release is used, because there is no check with
-release).

The result is that a variable of an enum type does not entirely act like the
base type even when you're not considering stuff like using is expressions
or std.traits to test something based on its type. It's implicitly
convertible to its base type but is not its base type. However, a bunch of
operations that IMHO really should not be legal on an enum are (e.g.
appending), and some which could be legal but should result in the base type
rather than the enum type (e.g concatenation or |ing) result in the enum
type, making it trivial to create enum variables with values that aren't in
the enum if you're not careful. Discussions have been had on this in the
past, and I'm firmly of the belief that the current design is a mistake in
this regard, but some (Andrei included) have argued that it's perfectly
legitimate to have an enum variable which is not one of the listed enum
values with the idea that you're defining a general type that has a few
known constants but the constants aren't all of the values. I think this
violates the idea of what an enum is (I think that an enum should always
define all valid values for that enum and no other values should be legal),
and it definitely doesn't play nicely with final switch, but for the moment,
we're stuck.

> Also it sounds to me like string enums are going to be slower
> performance wise than integer enums.

I expect so. How efficient an enum is depends entirely on what its base type
is and what you're doing with it. However, if all you're really looking for
is to have a string representation of the name of an enum, then you can have
the base type be int, and to!string and writeln will give you the string
representation of the name of the enum without the enum needing to be a
string. Whether it makes sense to use string as the base type of an enum
depends entirely on what you're trying to do with the enum, just like
whether you use a struct as the base type of an enum makes sense depends on
what you're doing. Sometimes, it can be very useful, but that doesn't mean
that it's always the best solution.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list