2016-11-23 23 views
1

我仍然必须处理Visual Basic 6.为什么VB6在编译时不检查对象类型的对应关系?

我刚刚发现只有在运行时强制执行对象类型的对应关系。例如参见this question


我很震惊地发现这一点,我总是依靠对物体进行类型安全检查。

有人知道这是否存在体系结构原因(这使得它至少是一个复杂的问题)?

如果涉及到多态性,我会理解它,但是当参数的类型是一个没有被其他类实现的类时,我在编译时就没有发现类型检查有问题...?

回答

4

历史教训

VB版本1至3是严格。类型一致性检查仍然在运行时进行,但是它更严格。如果您将字符串分配给一个整数,则会出现运行时错误。我不知道为什么只在运行时进行一致性检查 - 在猜测编译时检查很难实现。

在VB版本4语言已更改,以便(例如)将字符串分配给整数不会引发错误,但会隐式地将字符串值转换为整数。例如,如果字符串包含"0"""它将被转换为0。如果包含字符串,比如说"1E40",则会发生溢出错误。许多VB程序员(包括呃,我)都不喜欢这种变化,并称之为邪恶类型的强制。例如。大师Karl Peterson看到这个article

所以这个架构方法是“在猜测的时候尝试在运行时转换类型,只在不可能的时候引发错误”。这意味着,检查在运行时。我想原则上编译器可以检测到对象类型是私有的,并且没有被其他类实现的情况,并且在编译时检查,但我想这对编译器开发者来说不是优先考虑的。开发人员甚至可能会弄糊涂了解为什么某些任务在运行时被检查,而其他人则在编译时被检查。

在VB.Net中,默认行为与VB6相同,以便升级遗留代码。在VB.Net中优先采用Option Strict On,以便在编译时进行检查。编译时检查很有用,因为它们可以及早标记错误。

+0

很有意思的答案,谢谢。 但对于正常(非对象)类型,对于例程调用的ByRef(默认)参数,**是在编译时进行的! 现在我想到它可能大多是偶然的,因为允许代码的多个部分将相同变量视为具有不同类型_might_可行,但会非常复杂和混乱。 – gbr

+0

是的,考虑到隐式强制的事情,并且提到完全没有编译时检查(我没有意识到),很可能静态检查在VB开发人员心目中并不是很多。 – gbr

+0

顺便说一句,尝试在VB 2010(与选择严格关闭)我**做**得到一个编译器错误,尝试类似的问题,我提到的问题([expected-type-mismatch-error](https:/ /stackoverflow.com/questions/549357/expected-type-mismatch-error)),也许它只是在第一个.Net版本中丢失......? – gbr

2

只有接口被实现,而不是类。 VB6类Car隐式定义接口_Car,可以在任何外部项目(DLL)来实现,并且可以在组件类与任何其他接口(包括_Boat)捆绑

当你Dim c As Car它的界面_Car,这些会用来编译器,所以c可以在任何对象上持有对_Car接口的引用,而不仅仅是Car类的实例。例如。你可以编写一个实现了_Car_Boat接口的协调器Mix,所以Set c = New Mix编译和运行,所以在Sail c接口的QI实际上成功(认为“强制转换”成功)。

请注意,这不是upcast也不是downcast,因为_Car_Boat不受任何继承形式的约束。但这是COM允许你通过IUnknown接口实现的。

在现代语言中,他们决定你总是需要在代码中明确地向下转换(否则会出现编译错误),并且与“侧投”(如在设计的汽车/船例子中一样)你自己在腿上。

+0

我对最近的回复表示歉意,我起初花了几天的时间来看看你提出的,后来几乎没有时间。 (1/6) – gbr

+0

你提出了一些很好的观点。 我不认为我意识到“混合到船”的情景是可能的。我明白这是由于支持COM,但它似乎很疯狂!但也许这只是VB语法在类和接口之间的混淆。因此,“As”总是指向接口,并且对象不会被转换为任何东西,它们总是保持所有的接口包,而不管来自您正在查看的“接口窗口”(变量/参数)。 在试图变得聪明的VB做了一个大混乱,在我看来。 (2/6) – gbr

+0

我没有考虑到一个链接的外部组件可能会实现项目的一个类。这只会发生在ActiveX项目的非私有类中,对吧? (3/6) – gbr

相关问题