.Cast <t>扩展方法总是抛出InvalidCastException - 你应该如何使用这个方法?

时间:2016-11-22 05:44:04

标签: c# linq exception casting extension-methods

有几次我对.Cast<T> LINQ扩展方法感到好奇。我觉得“这听起来就像我在这种情况下所需要的”,但每当我尝试使用它时,我总会得到一个InvalidCaseException。我从来没有能够成功使用这种方法。这是检查异常的示例行:

Enumerable.Range(0,10).Cast<float>().ForEach(Console.Out.WriteLine);

int投射到float没有任何争议,为什么这种方法拒绝这样做?我可以通过简单地用.Cast<float>

替换.Select(x => (float)x)来解决这个问题并获得预期的效果
Enumerable.Range(0, 10).Select(x => (float)x).ForEach(Console.Out.WriteLine);

这不是太麻烦,但仍然,我只是不明白为什么Cast<float>方法不能为我做这个工作。

问题简而言之:您如何使用.Cast<T>扩展方法?

这与问题无关,但为了防止有人想知道,我在上面的代码片段中使用了自定义的ForEach扩展方法(标准版仅适用于列表):

static class Extensions
{
    public static void ForEach<T>(this IEnumerable<T> x, Action<T> l)
    {
        foreach (var xs in x) l(xs);
    }
}

2 个答案:

答案 0 :(得分:3)

如果您查看ReferenceSource Cast<TResult>方法的源代码,您会看到最后调用CastIterator<TResult>方法,如下所示:

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

如您所见,C#尝试从盒装对象转换为TResult,这是异常的原因。如果您想模仿问题,请尝试以下操作:

int a = 5;
object o = a;
float f = (float)o;

答案 1 :(得分:2)

撰写以下内容时:

select

您实际上并未投射该值。你正在转换它。 C#只为您提供了很好的语法。这里生成的IL是int a = GetInt(); var b = (float)a; ,它将堆栈顶部的值转换为浮点数。

conv.r4实际上正在进行演员表演,但并没有获得语法糖的精确性。

如果你要写:

Enumerable.Cast<T>

你可以,因为整数 可以转换为对象。