Why am I getting InvalidCastException?
I have following code snippet in c#
List<int> list = new List<int>() { 1, 23, 5, 3, 423, 3 };开发者_如何学运维
var query = list.Cast<double>().Select(d => d);
try
{
foreach (var item in query)
{
Console.WriteLine(item);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
It's compile perfectly,but when i am executing this I am getting exception.
Because you're typecasting from an int to double, it's not a conversion it's a type cast and this is somewhat different from when you cast int to double in the general case.
The Cast<T>
extension method uses the IL instruction unbox.any
While a C# cast like this
var x = (double)42;
Actually results in the IL instruction
conv.r8
Fundamentally unboxing an type as a different type is wrong and that's why you get the exception.
This question has the same answer and also links to a blog post by Eric Lippert.
list
contains ints
, which you attempt to cast to double
. Change your query to
var query = list.Select(d => (double)d);
Update
Here's the source for Enumerable.Cast
(.NET 4):
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) {
IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
if (typedSource != null) return typedSource;
if (source == null) throw Error.ArgumentNull("source");
return CastIterator<TResult>(source);
}
static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
foreach (object obj in source) yield return (TResult)obj;
}
As you can see, the CastIterator
attempts to cast an object
(which in this case is a boxed int
) to a double
. Unboxing operations only succeed if the target type is exactly the same as the original type that was boxed, so an exception is thrown. This link that John Leidegren provided explains in detail.
There is a difference between a .NET Framework type-cast and a C# type conversion. They are NOT the same. "Casting" int to double is a feature of the C# language, and of the language alone.
The C# compiler can convert an int to double using a special instruction for this purpose. The compiler knows, at compile time, that the source type is "int", the destination type is "double", and therefore can generate the proper instruction. This is not really a type cast in the .NET Framework sense.
System.Int32 cannot be type-cast to System.Double. The Cast extension method was compiled without knowing the exact types of the source and the destination collections, and therefore no special instructions for handling C# specific features were generated. The only code that is generated for the Cast extension method is a normal .NET type cast (casting classes to their base types, casting to object, and casting types to the interfaces they implement).
精彩评论