Reputation: 20384
For view model validation, I need to determine whether a value, of which I only have an object interface, is an enum and has the numeric value of -1.
I tried this:
// object value;
if (value?.GetType().IsEnum == true && (int)value == -1) return null;
It should work with my Model enums which are mostly based on int
.
But it fails when the value is a Visibility
enum (that happens to be also in the view model class and should be ignored for validation) which is based on byte
instead of int
and that seems not to be castable to int
. I could do some more testing but it shouldn't get too slow.
Is there a good simple solution for that? Maybe some test method in the Enum
class or something?
Upvotes: 3
Views: 220
Reputation: 43896
You can check the underlying type with GetEnumUnderlyingType()
:
Type t = value?.GetType();
if (t?.IsEnum == true &&
t?.GetEnumUnderlyingType() == typeof(int) &&
(int)value == -1)
return null;
Since a byte
can never be -1
, you don't need to check it. But you may need to extend the check for long
enums, too.
UPDATE:
I just tried around a little and found that Convert.ToInt32()
also solves your problem:
if (value?.GetType().IsEnum == true &&
Convert.ToInt64(value) == -1)
return null;
This seems cleaner and also works for all possible underlying types.
Another update: Unfortunatly the solution above is not as clean as I thought. Even with Convert.ToInt64()
solves the problem of long
values too big for Int32
, but it throws if you pass for example a ulong.MaxValue
.
So you have to choose a type that is large enough for all possible enum base types:
if (value?.GetType().IsEnum == true &&
Convert.ToDecimal(value) == -1)
return null;
Using Convert.ToDecimal()
this passes all the test cases that came up so far.
Upvotes: 6
Reputation: 4261
byte
can be casted to int
if it is not boxed with object
byte b = 1;
int i = (int)b; //works good
int f = (int)(object)b; //fails
So you could convert your variable to int
using Convert.ToInt32
method, as René Vogt suggested, or cast it to dynamic
instead casting to int
:
if (value?.GetType().IsEnum == true && (dynamic)value == -1) return null;
Although, operations with dynamic
are rather slow. In my opinion, soultion with Convert.ToInt32
is the most cleanable and efficient. This answer is just to point out, why you can not cast the object
to int
and suggest a dynamic
version of cast.
Upvotes: 0
Reputation: 111870
You could:
if (value != null)
{
var type = value.GetType();
if (type.IsEnum && object.Equals(Enum.ToObject(type, -1), value))
{
return null;
}
}
I had to do it in multiple lines to "cache" the GetType()
. The trick is using Enum.ToObject()
to "cast" -1
to the current Enum
type.
Note that casting will generate "strange" results:
public enum TestEnum : ulong
{
ValueMax = ulong.MaxValue
}
In this case, TestEnum.ValueMax
will return null
. This will happen for all the unsigned types.
Upvotes: 0
Reputation: 13421
In addition, one could consider using the Enum.IsDefined Method (Type, Object) to verify, if the value is a valid enum.
That does of course not cover the "check if it is -1" part.
Enum.IsDefined Method (Type, Object)
Returns an indication whether a constant with a specified value exists in a specified enumeration. Namespace: System Assembly: mscorlib (in mscorlib.dll)
[ComVisibleAttribute(true)] public static bool IsDefined( Type enumType, object value )
Parameters
enumTypeType
:System.Type
An enumeration type.
valueType
:System.Object
The value or name of a constant in enumType.Return Value
Type
:System.Boolean
becomestrue
if a constant in enumType has a value equal to value; otherwise,false
.Exceptions
ArgumentNullException' enumType or value is null.
ArgumentException` enumType is not an Enum. -or- The type of value is an enumeration, but it is not an enumeration of type enumType. -or- The type of value is not an underlying type of enumType.
InvalidOperationException
value is not type SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, UInt64, or String.Remarks
The value parameter can be any of the following:
- Any member of type enumType.
- A variable whose value is an enumeration member of type enumType.
- The string representation of the name of an enumeration member. The characters in the string must have the same case as the enumeration member name.
- A value of the underlying type of enumType.
If the constants in enumType define a set of bit fields and value contains the values, names, or underlying values of multiple bit fields, the IsDefined method returns false. In other words, for enumerations that define a set of bit fields, the method determines only whether a single bit field belongs to the enumeration. To determine whether multiple bit fields are set in an enumeration type that is tagged with the FlagsAttribute attribute, you can call the HasFlag method.
Upvotes: 0