VB与C#:为什么这是可能的

本文关键字:为什么 VB | 更新日期: 2023-09-27 18:26:59

这里有一些代码每当我想到它时都会困扰我。

Option Strict On
Module Module1
    Sub Main()
        For Each i As Integer In New String() {"why", "is", "this", "tolerated?"}
            ' compiles just fine.
        Next
    End Sub
End Module

C#根本不允许隐式地将字符串转换为整数。

class Program {
    static void Main(string[] args) {
        foreach (int i in new string[] {"that's", "better"}) {
            // will not compile, and for good reason.
        }
    }
}

为什么VB允许我们这么做?我试着从中获得乐趣,因为我在这里还相对较新,但我也很好奇。我相信有一些开发者会给出答案。

VB与C#:为什么这是可能的

这似乎是For Each语句的一个特性。根据文档,它在运行时进行评估。

来自链接:

当Option Strict设置为On时,缩小转换范围通常会导致编译器错误。然而,在For Each语句中,从组中的元素到元素的转换是在运行时计算和执行的,并且会抑制由缩小转换范围引起的编译器错误。

在下面的示例中,当Option Strict处于启用状态时,将m作为n的初始值的赋值不会编译,因为将Long转换为Integer是一种缩小范围的转换。然而,在For Each语句中,即使对数字的赋值需要从Long到Integer的相同转换,也不会报告编译器错误。在包含大数字的For Each语句中,当ToInteger应用于该大数字时,会发生运行时错误。

Microsoft在语言规范第10.9章:中对此表示歉意

迭代的当前元素被转换为循环控制变量的类型,即使转换是显式的,因为在语句中没有方便的地方引入转换运算符。当使用最常见的集合类型System.Collections.ArrayList时,这变得特别麻烦,因为它的元素类型是Object。这需要大量的循环,我们觉得这并不理想

具有讽刺意味的是,泛型允许创建一个强类型集合System.Collections.Generic.List(of T),这可能会让我们重新思考这个设计点,但为了兼容性,现在不能改变这一点。

作为对Mark答案的补充,以下是编译后的vb.net代码的样子。正如你所看到的,代码被编译为For。。。Next语句,并且只有在运行时尝试将字符串转换为整数时才会发生错误。

Dim VB$t_array$L0 As String() = New String() { "why", "is", "this", "tolerated?" }
Dim VB$t_i4$L0 As Integer
For VB$t_i4$L0 = 0 To VB$t_array$L0.Length - 1
    Dim i As Integer = Conversions.ToInteger(VB$t_array$L0(VB$t_i4$L0))
Next VB$t_i4$L0

我是不是唯一一个能看到VB代码中的数组是通用(变体)数组,而C#代码中包含严格的字符串数组?