2017-03-09 74 views
3

对于视图模型验证,我需要确定一个值,其中我只有一个对象接口,是一个枚举并具有数值-1。值是一个枚举和-1?

我尝试这样做:

// object value; 
if (value?.GetType().IsEnum == true && (int)value == -1) return null; 

应该与大多基于int我的模型枚举工作。

但当值是Visibility枚举(这正好也是在视图模型类,并应确认被忽略),这是基于byte而不是int,这似乎不被强制转换为int失败。我可以做更多的测试,但不应该太慢。

有没有一个很好的简单解决方案呢?也许在Enum类中有些测试方法或者什么?

+1

显示的枚举代码。 – HimBromBeere

+2

字节不能等于-1。 – mukh1n

+0

也许你需要将枚举基于'sbyte'而不是'byte'。 –

回答

6

你可以用GetEnumUnderlyingType()检查基本类型:

Type t = value?.GetType(); 
if (t?.IsEnum == true && 
    t?.GetEnumUnderlyingType() == typeof(int) && 
    (int)value == -1) 
    return null; 

由于byte永远不能-1,你并不需要检查它。但是您也可能需要延长long枚举的支票。


UPDATE

我只是想绕了一点,发现Convert.ToInt32()也解决了你的问题:

if (value?.GetType().IsEnum == true && 
    Convert.ToInt64(value) == -1) 
    return null; 

这似乎更清洁,也适用于所有可能的基础类型。


另一个更新:不幸的是,上面的解决方案并不像我想的那么干净。即使Convert.ToInt64()解决了long值太大的问题Int32,但它会抛出,如果你通过例如ulong.MaxValue

所以,你必须选择一个类型,它是足够大,为所有可能的枚举基本类型:

if (value?.GetType().IsEnum == true && 
    Convert.ToDecimal(value) == -1) 
    return null; 

使用Convert.ToDecimal()这通过所有想出了迄今为止测试用例。

+3

取为好,之后[枚举(C#参考)](https://msdn.microsoft.com/en-us/library/sbbt4032.aspx):_The批准类型枚举是'byte','sbyte','short','ushort','int','uint','long',或'ulong'._ – gaa

+0

在第二个例子中,如果发生什么'枚举MyEnum:long {MaxValue = long.MaxValue}}',然后'value = MyEnum.MaxValue'? :-) – xanatos

+0

@xanatos该死的权利,'Convert.ToInt64()'可以解决这个问题,但会抛出'ulong.MaxValue' ...我不断尝试... –

0

另外,如果该值是有效的枚举,则可以考虑使用Enum.IsDefined Method (Type, Object)来验证。

那当然不包括“检查它是否为-1”部分。

Enum.IsDefined方法(Type,对象)

是否与规定值的恒定存在于指定的枚举 返回一个指示。命名空间:系统程序集:mscorlib (在mscorlib中。DLL)

[ComVisibleAttribute(true)] public static bool IsDefined(Type enumType, object value) 

参数

enumTypeTypeSystem.Type 枚举类型。
valueTypeSystem.Object enumType中常量的值或名称。

返回值

TypeSystem.Boolean变得true如果在enumType恒定具有 值等于值;否则,false

例外

ArgumentNullException' enumType or value is null. ArgumentException` enumType不是枚举。 - 或者 - 值的类型是枚举,但它不是enumType类型的枚举。 - 或者 - 值的类型不是enumType的基础类型。

InvalidOperationException值不是类型SByte,Int16,Int32,Int64,Byte,UInt16,UInt32,UInt64或String。

备注

值参数可以是任何以下的:

  • 类型enumType的任何成员。
  • 一个变量,其值是enumType类型的枚举成员。
  • 枚举成员的名称的字符串表示形式。字符串中的 字符必须与枚举 成员名称具有相同的大小写。
  • enumType的基础类型的值。

如果enumType常数定义一组比特字段和值 的包含值,名称,或底层的多位 字段的值,则IsDefined方法返回false。换句话说,对于 定义一组位字段的枚举,该方法仅确定 是否一个位字段属于枚举。至 确定是否在使用FlagsAttribute属性标记的枚举类型 中设置了多个位字段,则可以调用 HasFlag方法。

0

,你可以:

if (value != null) 
{ 
    var type = value.GetType(); 

    if (type.IsEnum && object.Equals(Enum.ToObject(type, -1), value)) 
    { 
     return null; 
    } 
} 

我不得不这样做在多行 “缓存” 的GetType()。诀窍是使用Enum.ToObject()将“-1”投射到当前的Enum类型。

注意,铸造将产生 “奇怪” 的结果:

public enum TestEnum : ulong 
{ 
    ValueMax = ulong.MaxValue 
} 

在这种情况下,TestEnum.ValueMaxreturn null。这将发生在所有的无符号类型上。

0

byte可强制转换为int,如果它不与object

byte b = 1; 
int i = (int)b; //works good 
int f = (int)(object)b; //fails 

盒装所以,你可以使用Convert.ToInt32方法,如勒内·沃格特提出您的变量转换为int,或将其转换为dynamic代替铸造int

if (value?.GetType().IsEnum == true && (dynamic)value == -1) return null; 

尽管随着dynamic操作是相当缓慢的。在我看来,与Convert.ToInt32的灵魂是最清洁和高效的。这个答案只是想指出,为什么你不能投的objectint,并提出一个dynamic版本演员。

相关问题