0

I have the following enum that I need to validate based on client selections

    [Flags]
    enum Colour
    {
        Black = 1,
        Blue = 2,
        Green = 4,
        Yellow = 8
    }



var isValid = Enum.IsDefined(typeof(Colour), 5);

Why is returning false if 5 is a valid value (Colour.Black | Colour.Green)

codejunkie
  • 83
  • 7
  • Are you expecting the call to generate all possible combinations? It's only checking those that are actually defined. – Enigmativity Sep 12 '17 at 07:09
  • 3
    5 is not a defined value in your enum. It will only be true if you have a entry with the value 5. – Filnor Sep 12 '17 at 07:10
  • ok. how can it be checked then? – codejunkie Sep 12 '17 at 07:11
  • 5 is not defined.... how can the compiler be aware of fuse combinations that generate the value 5 – ΦXocę 웃 Пepeúpa ツ Sep 12 '17 at 07:11
  • 1
    5 = 4 + 1, check if 4 is defined and check if 1 is defined. – rene Sep 12 '17 at 07:12
  • I have a dozen of enums so I need to find a generic solution – codejunkie Sep 12 '17 at 07:13
  • 1
    @codejunkie - then what is the actual problem you are facing? Regarding the dozen enums – Gilad Green Sep 12 '17 at 07:14
  • @rene - `5` is also `2 + 3`. So should all combinations be tested? Or just "powers of two"? What if someone actually defines `3`? What would the sensible thing for the developers be to put as default behaviour? – Corak Sep 12 '17 at 07:15
  • @GiladGreen I dont understand your question – codejunkie Sep 12 '17 at 07:16
  • There isn't necessarily a generic solution since I've encountered some enums which represent a "hybrid" approach - where some values are meant to be selected between exclusively and other values are intended to be combined via or. Without understanding the semantics of that specific enum, you cannot know whether a value is well defined. (There's one somewhere in the BCL, can't find it at the moment) – Damien_The_Unbeliever Sep 12 '17 at 07:16
  • I assumed it was clear how the Flags attribute works but yes, it is powers of 2 in this case. @Corak – rene Sep 12 '17 at 07:17
  • So there is no way of checking whether the client input is valid? – codejunkie Sep 12 '17 at 07:21
  • @codejunkie the client enter a number? weird... but in any case, in the specific enum shown, you can check if it's between 1-15 – Ofir Winegarten Sep 12 '17 at 07:22
  • I want to avoid corrupt input that might cause problem in server. Because it is a web app someone can try to cause problems – codejunkie Sep 12 '17 at 07:26
  • @rene -- it is. But `5` still isn't a *defined* value. If someone just wants an `IsValid` method, the easiest could be: `return value < (maxEnumValue * 2);`, because every combination could be valid. -- but again, that wouldn't be what I (and seemingly the developers) would expect from a method called `IsDefined`. – Corak Sep 12 '17 at 07:27
  • I think the duplicate offers all the info the OP needs @Corak – rene Sep 12 '17 at 07:31

3 Answers3

2

Because it is proper result. "If enumType is an enumeration that is defined by using the FlagsAttribute attribute, the method returns false if multiple bit fields in value are set but value does not correspond to a composite enumeration value, or if value is a string concatenation of the names of multiple bit flags." See MSDN for details about how IsDefined works.

UPD: Solution for any enum:

static class EnumExtensions
{
    public static bool IsSuitable(Type enumType, int value)
    {
        if (!enumType.IsEnum)
        {
            throw new ArgumentException(nameof(enumType));
        }

        var entities = Enum.GetValues(enumType);
        int composite = 0;
        foreach (var entity in entities)
        {
            composite |= (int)entity;
        }

        return (composite | value) == composite;
    }
}

It gives this result:

var suit = EnumExtensions.IsSuitable(typeof(Colour), 5); // true
var suit2 = EnumExtensions.IsSuitable(typeof(Colour), 333); //false
Danil Eroshenko
  • 451
  • 2
  • 9
1

The return value of Enum.IsDefined() function is depend on the enum definition. you are actually checked if '5' is in the set of values from the enum you defined.

Michael Gabbay
  • 204
  • 3
  • 13
0
    [Flags]
    enum Colour
    {
        Black = 1,  // 0001
        Blue = 2,   // 0010
        Green = 4,  // 0100
        Yellow = 8  // 1000
    }

    static void Main(string[] args)
    {
        var isValid = Enum.IsDefined(typeof(Colour), 5); // 5 is 0101
    }

Enum.IsDefined: Returns an indication whether a constant with a specified value exists in a specified enumeration.

in your example you have values 1,2,4,8 why you thinking that value 5 should return true ??

    [Flags]
    enum Colour
    {
        Black = 1,
        Blue = 785,
        Green = 4,
        Yellow = 666
    }

    static void Main(string[] args)
    {
        var isValid = Enum.IsDefined(typeof(Colour), 666); // true
        var isValid2 = Enum.IsDefined(typeof(Colour), 785); // true
        var isValid3 = Enum.IsDefined(typeof(Colour), 5); // false
    }
Leon Barkan
  • 2,516
  • 2
  • 13
  • 36