热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么从接口值设置对象仅在if语句的一行上抛出invalidCastException

如何解决《为什么从接口值设置对象仅在if语句的一行上抛出invalidCastException》经验,为你挑选了1个好方法。

使用包含接口的if语句设置数组对象时,抛出InvalidCastException并需要理解为什么

我知道如何解决实际问题,我只是感到困惑为什么会这样。

请注意,customerOne和Two是接口(即ICustomer),而customers是“ Customer”的数组(不是接口)

只有当它是一个数组时,这才会出错,如果我尝试将单个对象设置为接口值,它将正常工作

Dim customerOne as ICustomer
Dim customerTwo as ICustomer

--- ^^这些被填充...然后我们创建一个数组:

Dim customers as Customer()

现在,奇怪的部分...

customers = {customerOne, customerTwo}

以上工作正常

customers = If(myBool, {customerOne,customerTwo}, {customerOne,customerTwo})

以上失败,并显示InvalidCastException

我希望If语句将返回与工作示例完全相同的值,因此不会引发InvalidCastException

有人知道这种行为的原因吗?



1> Steven Dogga..:

您的代码只能进行编译,因为您具有Option Strict Off,这使得某些错误在编译时无法进入RADAR,只有在运行时通过异常才能发现。如果您转弯Option Strict On(我和大多数其他人会建议您转弯),则此行无法编译:

customers = {customerOne, customerTwo}

它给出的错误是:

BC30512 Option Strict On不允许从'ICustomer'到'Customer'的隐式转换

这样做的原因是因为表达式{customerOne, customerTwo}的结果是ICustomer对象数组,因为这是变量的类型。在编译时,编译器无法知道这两个变量肯定会引用Customer对象,因为它们在理论上可以引用碰巧实现接口的任何类型的对象。因此,最好的办法是根据其初始值设定项中给出的变量确定数组的类型。

因此,该表达式求值为一个ICustomer()数组,但是您尝试将其分配给的变量是一个Customer()数组。由于Customer比更为具体ICustomer,因此不会自动允许该分配。为了使其能够编译,您必须显式转换它。您可以在数组初始值设定项中强制转换项目,以使其评估为正确的数组类型:

customers = {DirectCast(customerOne, Customer), DirectCast(customerTwo, Customer)}

或者,使用一些LINQ,您可以允许它评估为错误的数组类型,然后只对整个数组进行转换:

customers = {customerOne, customerTwo}.Cast(Of Customer)().ToArray()

但是,这些选项都不安全。它们都允许在运行时发生类型检查异常。因此,如果可能的话,最好以允许编译器在编译时安全地进行所有类型检查的方式重写代码。例如,如果将customers变量更改为ICustomer而不是具体Customer类型的数组,则可以正常工作:

Option Strict On

Public Module MyModule
    Public Sub Main()
        Dim myBool As Boolean = False
        Dim customerOne As ICustomer = New Customer()
        Dim customerTwo As ICustomer = New Customer()
        Dim customers As ICustomer()

        ' Both of these lines compile fine because the arrays are all ICustomer()
        customers = {customerOne, customerTwo}
        customers = If(myBool, {customerOne, customerTwo}, {customerOne, customerTwo})
    End Sub

    Public Class Customer
        Implements ICustomer
    End Class

    Public Interface ICustomer
    End Interface
End Module

至于三元If运算符抛出它的原因……好吧,这更复杂了,让我望而却步。我试图Option Strict Off不惜一切代价避免使用它,所以它的确切工作方式并不是我的专长。但是,总的来说,发生的情况是If操作员在中间增加了一层评估和类型推断,这阻止了VB为您执行自动类型转换的尝试。例如,如果您使用进行此操作Option Strict Off,它将起作用:

Dim customerOne As ICustomer = New Customer()
Dim customerTwo As ICustomer = New Customer()
Dim customers As Customer()
customers = {customerOne, customerTwo}

如果执行此操作,您将看到{customerOne, customerTwo}计算结果实际上是一个ICustomer()数组:

Dim customerOne As ICustomer = New Customer()
Dim customerTwo As ICustomer = New Customer()
Dim customers As Customer()
Dim temp As Object = {customerOne, customerTwo}
Console.WriteLine(temp.GetType().Name)

但是,如果这样做,它将在运行时引发异常:

Dim customerOne As ICustomer = New Customer()
Dim customerTwo As ICustomer = New Customer()
Dim customers As Customer()
Dim temp As Object = {customerOne, customerTwo}
customers = temp

它引发的异常是:

System.InvalidCastException:无法将类型为“ ICustomer []”的对象转换为类型为“ Customer []”的对象

只需将其分为两个步骤,强制其首先评估输入数组,它就会失败。仅当您创建数组并在同一命令中分配变量时,它才起作用。实际上,即使您在该中间变量上指定了正确的类型,它也会因相同的异常而失败:

Dim customerOne As ICustomer = New Customer()
Dim customerTwo As ICustomer = New Customer()
Dim customers As Customer()
Dim temp As ICustomer() = {customerOne, customerTwo}
customers = temp

这本质上就是If操作员正在做的事情。将其分为两个步骤,If操作员必须首先评估其操作数,以确定其本身将被评估为哪种类型(即,如果返回的是方法,则类似于它返回的内容)。中间的额外步骤使VB无法自动执行类型转换。具体为什么,我不能说。


总是很好的答案和很好的解释
推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了C函数ispunct()的用法及示例代码。ispunct()函数用于检查传递的字符是否是标点符号,如果是标点符号则返回非零值,否则返回零。示例代码演示了如何使用ispunct()函数来判断字符是否为标点符号。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文讨论了如何在dotnet桌面(Windows)应用程序中添加图标。作者提到可以使用dotnet命令行工具与resource.rc文件一起使用来为标准.NET核心应用程序添加图标。作者还介绍了在创建控制台应用程序时如何编辑projeto1.csproj文件来添加图标。 ... [详细]
author-avatar
mobiledu2502880517
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有