It's impossible to directly cast an int to an unknown type, so the compiler won't allow (TEnum)intEnumValue. The two casts you are doing now are actually subtly different: (object) boxes the int, while (TEnum) casts the boxed int to a TEnum, which is statically allowed because an expression which is of static type object might actually be of runtime type TEnum.
There might also be some further subtlety: Normally, a boxed int can only be unboxed to int. I think I've explained why the conversion is allowed by the compiler, but not why it's also allowed by the runtime. Perhaps conversion to TEnum is only allowed at runtime because TEnum happens to be an enum that has int as its base type? I think I remember reading that enums in the CLR are really just instances of their base type.
Edit: I confirmed my suspicion:
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;
}
So we can safely say that (TEnum) on a boxed int is only valid if TEnum is in fact an int under the covers!