与C#相比,VB.NET是弱类型的吗?

时间:2011-04-15 03:21:56

标签: c# vb.net type-safety

昨天我正在接受采访时,我的采访者(不可否认自称是该专题的专家)表示“VB.NET比C#更弱” - (同时他不能回想一个例子)。

这句话对我来说似乎不正确(特别是考虑到两种语言都为他们的类型使用相同的框架库),我这样建议,也许他对打开/关闭Option Strict或Option Infer的选项感到困惑。 / p>

与此同时,我知道VB.NET会出现类型强制的情况 - 偶尔导致意外结果(虽然我也无法回想起在什么条件下) - (其实我想我只记得它主要是在什么时候使用不同类型执行算术运算 - 而其他语言将强制您显式(?))。

那么有人可以澄清一下,VB.NET是否会以某种方式更弱地输入C#,如果是这样,你能提供例子吗?

4 个答案:

答案 0 :(得分:16)

如果没有澄清,“弱打字”和“强打字”实际上毫无意义。它们的使用方式通常意味着“类型系统具有我不喜欢的功能”或“类型系统具有我喜欢的功能”。听起来你的面试官并不清楚这些术语的含义,因此可能不应该在面试中询问有关他们的问题。

类型系统有很多功能,不同的人说是“强类型”和“弱类型”。例如,有些人说“强类型”意味着“每个对象在运行时都知道自己的类型”。有人说“强类型”意味着编译器知道每个变量和表达式的确切类型。有人说这意味着编译器在每个变量和表达式上都有不精确的类型边界。等等。类型系统的每个功能都可以算作“强”的点。

我说放弃整个毫无根据的“强”和“弱”打字概念,并谈论你的意思。

C#和VB类型系统之间的差异很小,特别是因为向C#4.0添加了“动态”。 C#和VB都使用CLR类型系统,其中每个对象都知道自己的类型,并且运行时检测到非法类型转换(在代码运行时或通过验证程序时)并转换为异常。两者都具有类的单继承和接口的多继承。两者都区分了值类型和引用类型。等等。

C#和VB类型系统之间的主要区别在于VB支持可选地拨打编译时静态类型检查,并将类型检查推迟到运行时,更像是动态类型语言。当与为动态类型系统设计的对象模型进行互操作时,这非常方便。我们为C#4.0添加了一个类似的功能,但是为了保持C#4.0对静态类型的历史支持,该功能基于将某些表达式静态键入为“动态”,然后通过在运行时再次启动类型分析器来解决并对活动对象进行类型分析。

有关此主题的更多信息,请访问我的博客:

http://ericlippert.com/2012/10/15/is-c-a-strongly-typed-or-a-weakly-typed-language/

答案 1 :(得分:4)

作为一种采访策略,最好说“你是对的,它的类型更弱,但只适用于Option Strict Off或Option Infer off等特定设置”

大多数人更乐意被告知“你是对的”,而不是“你感到困惑”:)

答案 2 :(得分:4)

(我之前从未真正使用过VB,所以这对我来说也是新的)

他们指的是Option Strict语句,或者更确切地说当你省略它时会发生什么。

只要您Option Explicit关闭,以下VB就会编译并运行perfeclty:

Class Widget
    Sub Method1()

    End Sub
End Class

Sub Main()
    Dim someInt As Integer
    Dim someDouble As Double
    Dim someObj As Object = New Widget

    someDouble = 1234567890.9876542
    someInt = someDouble
    Call someObj.Method1()
    Call someObj.Method2() ' causes runtime error
End Sub

上面隐式地将double转换为整数,在Method1引用上调用方法Object,甚至调用方法Method2(甚至不存在) - 没有它将使用Option Strict On在C#或VB中编译。

这绝对符合C#的“不作为strongly typed”的定义,尽管该术语似乎相当主观。

更新:我们可以使用ILSpy通过查看已编译的程序集(在C#中)来揭示此处发生的“魔法”:

object obj = new Module1.Widget();
double num = 1234567890.9876542;
int i = Math.Round(num);
NewLateBinding.LateCall(obj, null, "Method1", new object[0], null, null, null, true);
NewLateBinding.LateCall(obj, null, "Method2", new object[0], null, null, null, true);

这解释了为什么VB.Net编译器能够执行在CLR中看起来非法的事情,尽管它似乎确实会带来某种运行时性能损失。

答案 3 :(得分:1)

VB.NET允许两者。如评论中所述,您可以通过将Option Strict设置为ON或OFF来在项目(或文件)中设置此项。

MSDN documentation here更多地讨论了该选项的作用。