Enum.IsDefined with flagged enums

2019-02-21 23:12发布

问题:

I'm currently reading the book C# 4.0 in a Nutshell, which by the way I think is an excellent book, even for advanced programmers to use as a good reference.

I was looking back on the chapters about the basics, and I came across a trick to tell if a certain value is defined in an Enum when using flagged enums.
The book states that using Enum.IsDefined doesn't work on flagged enums, and suggests a work-around like this :

static bool IsFlagDefined(Enum e)
{
    decimal d;
    return (!decimal.TryParse(e.ToString(), out d);
}

This should return true if a certain value is defined in an enum which is flagged.

Can someone please explain to me why this works ?

Thanks in advance :)

回答1:

Basically, calling ToString on any enum value of a type declared with the [Flags] attribute will return something like this for any defined value:

SomeValue, SomeOtherValue

On the other hand, if the value is not defined within the enum type, then ToString will simply produce a string representation of that value's integer value, e.g.:

5

So what this means is that if you can parse the output of ToString as a number (not sure why the author chose decimal), it isn't defined within the type.

Here's an illustration:

[Flags]
enum SomeEnum
{
    SomeValue = 1,
    SomeOtherValue = 2,
    SomeFinalValue = 4
}

public class Program
{
    public static void Main()
    {
        // This is defined.
        SomeEnum x = SomeEnum.SomeOtherValue | SomeEnum.SomeFinalValue;

        Console.WriteLine(x);

        // This is not (no bitwise combination of 1, 2, and 4 will produce 8).
        x = (SomeEnum)8;

        Console.WriteLine(x);
    }
}

The output of the above program is:

SomeOtherValue, SomeFinalValue
8

So you can see how the suggested method works.



回答2:

If the value of e isn't can't be created using a combination of flags ToString() defaults to an integral number. And integral numbers will of course parse as decimal.

But why your code parses as decimal isn't entirely clear to me. But probably integral types won't work for both enums that are based in Int64 and UInt64.