c# - How to avoid impossible enum values? -


say have following enum:

[flags] enum intflags {   = 1 << 0,   b = 1 << 1,   c = 1 << 2,    aandb = | b } 

and want build helper method sets flags following:

private static intflags set(intflags values, intflags target) {   return target | values; } 

is there flexible way sanity checking? should impossible set values don't exist in enum or not combination of existing values.

stuff following should not possible:

intflags flags = 0; flags = set(0, flags); flags = set((intflags)int.maxvalue, flags); flags = set(~intflags.a, flags); 

i guess doing check against existing values like:

private static intflags set(intflags values, intflags target) {   if (!enum.getvalues(typeof(intflags)).cast<intflags>().contains(values))     throw new argumentexception();    return target | values; } 

won't work because setting values like

intflags flags = 0; flags = set(intflags.a | intflags.c, flags); 

should allowed.

i think might work:

intflags set(intflags values, intflags target) {         int intvalue;   if (int.tryparse(values.tostring(), out intvalue))   {     throw new argumentexception();   }    ...  } 

but relies on fact i'm using flags attribute on enum.

edit

i found enum.isdefined() method. works nicely

assert.false(enum.isdefined(typeof(intflags), (intflags)int.maxvalue)); assert.false(enum.isdefined(typeof(intflags), 0)); assert.false(enum.isdefined(typeof(intflags), ~intflags.a)); 

but fails requirements combined values

assert.true(enum.isdefined(typeof(intflags), intflags.a | intflags.c)); //fails 

there's no way statically prohibit users of enum creating enum representing value of underlying type. can such validation @ runtime, showed in question.

if you're looking simple enough way of validating, @ runtime, if particular enum value valid combination of flags, that's simple enough check, assuming defined enum values increasing powers of two. such enum valid values go 0 1 less next highest power of two, check become:

if((int)values > 0 && (int)values >= 1 << 3))     throw new argumentexception(); 

technically remove possible unmapped values must mapping every single value, that's not particularly practical solution.

all you're left if either of aren't option not use enum, instead use own custom type has exact semantics want:

public class intflags {     public int value { get; private set; }     private intflags(int value)     {         this.value = value;     }      public static readonly intflags = new intflags(1);     public static readonly intflags b = new intflags(2);     public static readonly intflags c = new intflags(4);      public static intflags operator |(intflags first, intflags second)     {         return new intflags(first.value | second.value);     }     public override bool equals(object obj)     {         return equals(obj intflags);     }     public override bool equals(intflags obj)     {         return obj != null && value == obj.value;     } } 

Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

jsf - How to ajax update an item in the footer of a PrimeFaces dataTable? -

jquery - Keeping Kendo Datepicker in min/max range -