嗨,
我只是注意到Enumerable.Cast<T>扩展方法有些奇怪......似乎它无法转换int为long,即使这个演员是完全合法的.
以下代码失败InvalidCastException:
foreach (var item in Enumerable.Range(0,10).Cast<long>())
{
Console.WriteLine(item);
}
Run Code Online (Sandbox Code Playgroud)
但是这个代码,我认为是相同的,确实有效:
foreach (var item in Enumerable.Range(0,10).Select(i => (long)i))
{
Console.WriteLine(item);
}
Run Code Online (Sandbox Code Playgroud)
谁能解释这种行为?我用Reflector查看了Cast方法的代码,但是Reflector无法解释迭代器块,所以很难理解......
Rex*_*x M 16
相关部分Cast:
this.<>2__current = (TResult)this.<obj>5__ab;
Run Code Online (Sandbox Code Playgroud)
我们可以使用以下代码模仿:
int foo = 1;
long bar = Cast<long>(foo); //oh noes!
T Cast<T>(object input)
{
return (T)input;
}
Run Code Online (Sandbox Code Playgroud)
哪个也失败了.这里的关键是在演员阵容中,它是一个对象.不是int.这失败了,因为我们只能从对象中取消打包到我们想要的确切类型.我们是从物体出发 - 这可能是盒装长,但事实并非如此.这是一个盒装的int.Eric Lippert在他的博客上对此进行了讨论:
我们已经决定取消装箱只能拆箱到确切的类型.如果你想调用那个可以做到这一切的慢速方法,它可用 - 你可以随时调用转换......
在你的代码中,你没有处理盒装的int(一个对象),你有一个int.
Luk*_*keH 10
与大多数其他LINQ扩展方法不同,Cast扩展非泛型IEnumerable接口,而不是IEnumerable<T>.
这意味着调用int生成的值由调用的底层枚举Range器装箱,然后Cast调用它们尝试将它们转换为long失败,因为值只能取消装箱到完全相同的类型.
您可以通过显式装箱int值来模仿第二个循环中的相同异常行为:
foreach (var item in Enumerable.Range(0, 10).Select(i => (long)(object)i))
{
Console.WriteLine(item);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7058 次 |
| 最近记录: |