2009-09-24 76 views
2

我修改了扩展方法Thorarin了响应this问题上的一个int而不是字符串工作蒙上错误到'TEnum'。“在最后一行。诠释在通用扩展

如果该行被更改为此:

return (TEnum)(object)intEnumValue; 

它编译和作品。

为什么int需要先转换为object?

回答

5

无法将int直接投射到未知类型,因此编译器将不允许(TEnum)intEnumValue。这两个石膏你现在正在做实际上是微妙的不同:(object)int,而(TEnum)铸盒装intTEnum,这是静态允许的,因为它是静态类型object的表达可能实际上是运行时类型TEnum的。

可能还有一些微妙之处:通常,盒装intcan only be unboxed to int。我想我已经解释了编译器允许转换的原因,但不是为什么它也被运行时所允许。也许转换为TEnum只允许在运行时,因为TEnum碰巧是一个枚举有int作为其基本类型?我想我记得读过CLR中的枚举实际上只是它们基类型的实例。

编辑:我证实了我的怀疑:

public static void Main() 
{ 
    int value = 1; 

    IntEnum i = ToEnum<IntEnum>(value); // Valid cast, runs fine. 
    ByteEnum b = ToEnum<ByteEnum>(value); // Invalid cast exception! 
} 

public enum ByteEnum : byte { } 

public enum IntEnum : int { } 

public static TEnum ToEnum<TEnum>(int value) 
{ 
    return (TEnum)(object)value; 
} 

所以我们可以有把握地说,(TEnum)在盒装int是唯一有效的,如果TEnum实际上是在幕后的int

+0

是否有更直接的方法从Enum的基础类型转到Enum? – 2009-09-24 14:50:46

+1

Enum.ToObject(typeof(TEnum),intEnumValue)as TEnum – plinth 2009-09-24 14:53:41

0

当您使用(TEnum)intEnumValue进行强制转换时,编译器不知道要使用哪种类型的TEnum类。由于int只能隐式转换为某些类,编译器会失败。铸造对象是可以接受的,然后TEnum是一个对象,所以铸造也是可能的。

0

TEnum是一种任意类型。你可以投一个int到矩形?到DateTime?编译器不知道,不幸的是规范说你不能在它上面添加一个约束。

2

Eric Lippert有关于此类问题的博客文章here。基本上,有几种不同类型的'cast',从int到TEnum可能是其中的一种。所以,唯一安全的方法是将int整理到一个对象中,然后在运行时尝试将其转换为TEnum。你不能直接从int到TEnum,因为需要做什么取决于TEnum是什么,并且只在运行时才知道。