有几次我对.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);
}
}
答案 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>
你可以,因为整数 可以转换为对象。