泛型扩展中的Int cast错误

时间:2009-09-24 14:44:30

标签: c# generics casting

我修改了Thorarin在回答this问题时提供的扩展方法,以处理int而不是字符串:

public static TEnum ToEnum<TEnum>(this int intEnumValue, TEnum defaultValue)
{
    if (!Enum.IsDefined(typeof(TEnum), intEnumValue))
        return defaultValue;
    return (TEnum)intEnumValue;
}

编译器给出错误“无法将类型'int'转换为'TEnum'。”在最后一行。

如果该行更改为:

return (TEnum)(object)intEnumValue;

它编译并运作。

为什么首先需要将int转换为对象?

4 个答案:

答案 0 :(得分:5)

int直接转换为未知类型是不可能的,因此编译器不允许(TEnum)intEnumValue。您现在正在进行的两个演员实际上略有不同:(object)int,而(TEnum)将框int投放到TEnum,这是静态的允许,因为静态类型object的表达式实际上可能是运行时类型TEnum

可能还会有一些细微之处:通常情况下,装箱int can 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的情况下才有效!

答案 1 :(得分:2)

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

答案 2 :(得分:0)

使用(TEnum)intEnumValue进行转换时,编译器不知道TEnum将成为何种类。由于int只能隐式转换为某些类,因此编译器会失败。可以接受转换为对象,然后TEnum是一个对象,因此也可以进行转换。

答案 3 :(得分:0)

TEnum是一种任意类型。你能把int转换为Rectangle吗?到DateTime?编译器不知道,不幸的是规范说你不能在它上面添加约束。