为什么我会收到 InvalidCastException?

发布于 2024-10-21 18:01:28 字数 501 浏览 2 评论 0原文

我在 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);

            }

它可以完美编译,但是当我执行此代码时,我遇到了异常。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

百思不得你姐 2024-10-28 18:01:28

因为您是从 int 类型转换为 double,所以这不是转换,而是类型转换,这与一般情况下将 int 类型转换为 double 有所不同。

Cast 扩展方法使用 IL 指令 unbox.any

而像这样的 C# 强制转换

var x = (double)42;

实际上会导致 IL 指令

conv.r8 

从根本上将类型拆箱为不同类型是错误的这就是为什么你会得到例外。

这个问题有相同的答案,还链接到 博客埃里克·利珀特 (Eric Lippert) 发表的文章。

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 包含 ints,您尝试将其转换为 double。将查询更改为

var query = list.Select(d => (double)d);

Update

以下是 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; 
} 

如您所见,CastIterator 尝试强制转换object(在本例中是装箱的int)到double。仅当目标类型与装箱的原始类型完全相同时,拆箱操作才会成功,因此会引发异常。 John Leidegren 的此链接提供详细解释。

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.

温柔嚣张 2024-10-28 18:01:28

.NET Framework 类型转换和 C# 类型转换之间存在差异。它们不一样。 “将 int 转换为 double”是 C# 语言的一项功能,也是该语言独有的功能。

为此,C# 编译器可以使用特殊指令将 int 转换为 double。编译器在编译时知道源类型是“int”,目标类型是“double”,因此可以生成正确的指令。这实际上并不是 .NET Framework 意义上的类型转换。

System.Int32 无法类型转换为 System.Double。 Cast 扩展方法是在不知道源集合和目标集合的确切类型的情况下编译的,因此没有生成用于处理C# 特定功能的特殊指令。为 Cast 扩展方法生成的唯一代码是普通的 .NET 类型转换(将类转换为它们的基类型、转换为对象以及将类型转换为它们实现的接口)。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文