What about a more complete approach?
Define a few caches:
private static GenericAlias.Dictionary<Type, long> aoCompositeValues = new GenericAlias.Dictionary<Type, long>();
private static GenericAlias.Dictionary<Type, long[]> aoArrayOfValues = new GenericAlias.Dictionary<Type, long[]>();
Now some methods to fill the caches (may or may not be private [I do think private is better]):
private static long EnumCompositeValue(Type poType)
{
if (poType.IsEnum == false)
throw new ArgumentException("poType.IsEnum == false");
if (aoCompositeValues.ContainsKey(poType) == false)
{
long nCompositeValue = 0;
foreach (object enumValue in Enum.GetValues(poType))
nCompositeValue |= Convert.ToInt64(enumValue);
aoCompositeValues[poType] = nCompositeValue;
}
return aoCompositeValues[poType];
}
private static long[] EnumArrayOfValues(Type poType)
{
if (poType.IsEnum == false)
throw new ArgumentException("poType.IsEnum == false");
if (aoArrayOfValues.ContainsKey(poType) == false)
{
GenericAlias.List<long> anValues = new GenericAlias.List<long>();
foreach (object enumValue in Enum.GetValues(poType))
anValues.Add(Convert.ToInt64(enumValue));
aoArrayOfValues[poType] = anValues.ToArray();
}
return aoArrayOfValues[poType];
}
Then add a few general validation methods:
public static bool EnumIsValid(Enum penumValue, bool plAlloweZero)
{
Type oType = penumValue.GetType();
long nValue = Convert.ToInt64(penumValue);
if (oType.IsDefined(typeof(FlagsAttribute), false))
if (nValue == 0)
return plAlloweZero;
else
return (EnumCompositeValue(oType) & nValue) == nValue;
else
if (Array.IndexOf<long>(EnumArrayOfValues(oType), nValue) < 0)
return (nValue == 0) && plAlloweZero;
else
return true;
}
public static bool EnumIsValid(Type poType, long pnValue, bool plAlloweZero)
{
if (poType.IsEnum == false)
throw new ArgumentException("poType.IsEnum == false");
if (poType.IsDefined(typeof(FlagsAttribute), false))
if (pnValue == 0)
return plAlloweZero;
else
return (EnumCompositeValue(poType) & pnValue) == pnValue;
else
if (Array.IndexOf<long>(EnumArrayOfValues(poType), pnValue) < 0)
return (pnValue == 0) && plAlloweZero;
else
return true;
}
And now use those to create a few generic validation methods:
public static bool IsValid<T>(Enum penumValue)
where T : struct
{
return EnumIsValid(typeof(T), Convert.ToInt64(penumValue), false);
}
public static bool IsValid<T>(Enum penumValue, bool plAlloweZero)
where T : struct
{
return EnumIsValid(typeof(T), Convert.ToInt64(penumValue), plAlloweZero);
}
public static bool IsValid<T>(long pnValue)
where T : struct
{
return EnumIsValid(typeof(T), pnValue, false);
}
public static bool IsValid<T>(long pnValue, bool plAlloweZero)
where T : struct
{
return EnumIsValid(typeof(T), pnValue, plAlloweZero);
}
And lastly we create a few extension methods:
You need to change the access level of 'Class1Test.EnumCompositeValue' to 'protected internal' (if this is in a different class).
public static class Extentions
{
public static long CompositeValue(this Type poEnumType)
{
return Class1Test.EnumCompositeValue(poEnumType);
}
public static long CompositeValue(this Enum penumValue)
{
return Class1Test.EnumCompositeValue(penumValue.GetType());
}
public static bool IsValid(this Enum penumValue)
{
return Class1Test.EnumIsValid(penumValue, false);
}
public static bool IsValid(this Enum penumValue, bool plAlloweZero)
{
return Class1Test.EnumIsValid(penumValue, plAlloweZero);
}
}
Not to forget a unit-test:
[Test]
public void EnumValidation()
{
System.Diagnostics.Debugger.Break();
Assert.False(EnumIsValid((Enum1)0, false));
Assert.True(EnumIsValid((Enum1)0, true));
Assert.True(EnumIsValid((Enum1)1, false));
Assert.True(EnumIsValid((Enum1)2, false));
Assert.True(EnumIsValid((Enum1)3, false));
Assert.True(EnumIsValid((Enum1)4, false));
Assert.True(EnumIsValid((Enum1)5, false));
Assert.True(EnumIsValid((Enum1)6, false));
Assert.True(EnumIsValid((Enum1)7, false));
Assert.False(EnumIsValid((Enum1)8, false));
System.Diagnostics.Debugger.Break();
Assert.False(EnumIsValid((Enum2)0, false));
Assert.True(EnumIsValid((Enum2)0, true));
Assert.True(EnumIsValid((Enum2)1, false));
Assert.False(EnumIsValid((Enum2)2, false));
Assert.True(EnumIsValid((Enum2)3, false));
Assert.True(EnumIsValid((Enum2)4, false));
Assert.True(EnumIsValid((Enum2)5, false));
Assert.False(EnumIsValid((Enum2)6, false));
System.Diagnostics.Debugger.Break();
Assert.False(((Enum1)0).IsValid());
Assert.True(((Enum1)0).IsValid(true));
Assert.True(Enum1.A.IsValid());
Assert.True(Enum1.B.IsValid());
Assert.True(Enum1.C.IsValid());
Assert.True((Enum1.A | Enum1.B).IsValid());
Assert.True((Enum1.A | Enum1.C).IsValid());
Assert.True((Enum1.B | Enum1.C).IsValid());
Assert.True((Enum1.A | Enum1.B | Enum1.C).IsValid());
Assert.False(((Enum1)8).IsValid());
}
Regards,
Frans de Wit.
Happy enum'ing :)
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.