应用于通用枚举集合的Cast <int> .Cast <int?>导致无效的强制转换异常</int?> </int>

时间:2013-11-29 19:59:13

标签: c# casting enums type-conversion

enum Gender { Male, Female }

var k = new[] { Gender.Male }.Cast<int>().ToList().Cast<int?>().ToList(); //alright

var p = new[] { Gender.Male }.Cast<int>().Cast<int?>().ToList(); //InvalidCastException

第二种情况的原因是什么?我知道我不能直接将enum装箱int?Cast<int>.Cast<int?>,但我会进行两阶段演员,即object o = Gender.Male; int i = (int)o; // so here the cast is not to an entirely different type, which works 应该有效。

修改

考虑到以下情况,这是令人惊讶的:

{{1}}

2 个答案:

答案 0 :(得分:4)

好的,我已经找到了原因,这仍然很奇怪。我应该首先自己检查Cast<T>实施!

这就是Cast<T>的实施方式:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
{
    IEnumerable<TResult> enumerable = source as IEnumerable<TResult>;
    if (enumerable != null)
    {
        return enumerable; // this is the culprit..
    }
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    return Enumerable.CastIterator<TResult>(source);
}

private static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source)
{
    foreach (object current in source)
    {
        yield return (TResult)((object)current);
    }
    yield break;
}

现在问题出在第一次 Cast<int>来电:

new[] { Gender.Male }.Cast<int>()

此处source as IEnumerable<TResult>其中sourcenew[] { Gender.Male }TResultint 在泛型方法中返回非空值(这基本上意味着(new[] { Gender.Male }在通用上下文中是IEnumerable<int>,因此它返回相同的可枚举回Gender[],并在下一个Cast<int?>调用中,实际执行强制转换,从Genderint?失败。至于为什么在通用上下文中发生这种情况,catch it in this question

答案 1 :(得分:1)

这是由于延期执行。后一个语句实际上会尝试将Gender.Male转换为int?。相反,第一个语句实际上对int执行强制转换操作,并在推迟执行以将其转换为List<int>之前得到int?;显然intint?已经定义了隐含转换。