在 VB.NET 中,所有类型的变量都允许 IMPLICIT 变量声明(= New)吗?
In VB.NET, is IMPLICIT variable declaration (= New) allowed for all types of variable?
我将 Java 程序翻译成 VB.net。程序编译无误。
当我第一次执行程序时,程序在下一行崩溃
If oEnvironMap.isEmpty() Then
表示
System.MissingMemberException : public member 'isEmpty' from 'SortedDictionary(Of String,String)' type is not foundable
其中 oEnvironMap
声明行在后面
Private oEnvironMap = New SortedDictionary(Of String, String)
如果我添加 as
单词,如下面的代码
Private oEnvironMap as SortedDictionary(Of String, String) = New SortedDictionary(Of String, String)
构建应用程序 return 与 oEnvironMap
一起使用的方法有很多错误。
就我个人而言,我认为使用隐式声明来声明 VB.Net 变量是允许的。
我现在发现它不适用于作为字典的复杂数组!
这是 Visual Studio Community 2019 中的错误,我可以与 MSDN 沟通,还是仅仅是个人误解?
我知道这不会回答 'implicit variable' 的问题,但可能有助于解决 OP 的问题。
正如评论所说,.net 中没有针对 SortedDictionary(Of TKey, TValue)
类型的方法
您将需要测试 'Count' 属性 - 如果您的对象为 Nothing(在 C# 中为 null),它将抛出异常
或者您可以使用 .net
的 LINQ-函数之一
例如
导入 Linq(确保引用 System.Linq.dll
)
Imports System.Linq
并测试你的词典
If Not oEnvironMap.Any() Then
'is empty
end if
VB 中有三个选项与此处相关,您应该了解每个选项的作用。
Option Explicit
实际上是可以允许隐式声明的。它默认是 On
,永远不要变成 Off
。当 Off
时,您可以在代码中引入变量而无需事先声明。当 On
您必须在使用前声明每个变量。
Option Infer
是相当新的,是与 LINQ 一起引入的,以支持匿名类型。当 Off
时,所有变量都必须显式指定其数据类型,或者在允许的情况下,它们将默认为类型 Object
。当On
时,可以通过在声明变量的地方初始化变量来隐式指定变量的类型。无论该表达式的 return 类型是什么,都将为该变量推断类型。默认情况下它是 On
,可能应该保持这种状态,但如果您不使用匿名类型并且不介意显式指定每个变量的类型,则可以将其变为 Off
。成员变量不支持类型推断。
Option Strict
是争论的焦点。默认是Off
,主要是为了方便VB6代码的升级,也是为了让语言对初学者更加宽容。您应该在任何现有项目的属性以及 IDE 选项中将其设置为 On
,以便所有未来项目默认为 On
。当 Off
时,您可以省略任何变量、属性 或方法的任何数据类型规范,除非可以进行类型推断,否则它们将默认为 Object
。您还可以在设置变量或属性或传递方法参数时依赖隐式转换。后期绑定也是允许的,即访问编译器无法确认存在且必须在 运行 时间确认的成员。在几乎所有情况下,这都是不好的。 Option Strict
默认情况下应为 On
,因此您必须始终指定和使用正确的数据类型。在需要后期绑定的极少数情况下,您可以在包含实际需要它的最少代码的文件的文件级别打开 if Off
。
在您的特定情况下,问题是您有 Option Strict Off
,因此您的变量类型为 Object
。这与 Option Infer
无关,因为字段不支持类型推断。编译器不知道它所引用的对象会有哪些成员,所以它可以让你做任何事情。您尝试访问一个成员,但直到 运行 时间才确定。
转向 Option Strict On
,指定该字段的类型,然后仅在您的代码中使用该类型实际具有的成员,这将由编译器强制执行,而不是推迟到 运行 时间.
您可以通过以下多种方式在 VB 中创建变量。我会选择一些基本的东西,比如用一个字符 c
制作一个新字符串,所以在右边我们总是有“一个字符串”
Private s = New String("c"c, 1) 's is Object, compilation fails if Option Strict On even if Option Infer On
Private t As New String("c"c, 1) 't is String, shorthand of below
Private u As String = New String("c"c, 1) 'u is String
Private Sub Blah()
Dim x = New String("c"c, 1) 'x is Object if Option Infer Off, and fails to compile with Option Strict On but succeeds if Off. x is String if Option Infer On and compilation succeeds regardless of Option Strict
Dim y As New String("c"c, 1) 'y is String, shorthand of below
Dim z As String = New String("c"c, 1)
End Sub
区分私有成员变量 s 和局部 Dim 变量 x 可能很重要。
关闭 Option Strict 和 Infer Off,所有这些都将编译,但 s
和 x
将是 Object,intellisense 将只显示 Object 成员。 VB 将在运行时解决问题并将它们视为字符串,但如果您尝试使用 String 上不可用的内容(它仍然是一个字符串,只是“看起来像对象”),您会收到错误消息
在 Option Strict On 和 Infer Off 的情况下,s 和 x 将无法编译,您需要在某处使用“As”以将它们键入为字符串。 Intellisense 将起作用,因为编译器将变量解析为字符串,因为它们已经被 As'd
使用 Option Infer On,您可以编写 Dim x = ...
,因为推断会查看右侧并看到它是一个字符串,然后为您键入 x 作为字符串,但这仅适用于Dim
的局部变量,而不是 class 的成员变量。这意味着使用 Strict On 和 Infer On 你仍然会得到一个编译器错误,但这次只是在 Private s
上,因为它还没有 As
并且 Infer 没有 As
为你
所有这些都与泛型类型无关——任何提到 X(Of...) 的东西——你可以将 New String("c"c, 1)
换成 New Dictionary(Of String, Int)
并体验所有相同的规则
因此你的 vs 的行为是:
Private oEnvironMap = New SortedDictionary(Of String, String)
Strict 关闭,Infer 无关紧要,oEnvironMap 是一个对象,不会发生编译器错误,因为 VB 将其记为“必须在运行时计算出来”。在运行时,结果 isEmpty
不是一个东西 -> 异常
如果你给它一个类型:
Private oEnvironMap As New SortedDictionary(Of String, String)
Private oEnvironMap As SortedDictionary(Of String, String) = New SortedDictionary(Of String, String)
突然间,编译器 知道它是一个字典,并开始在编译时找出所有错误(之前会在运行时发生)。作为编译的一部分,它现在可以告诉您“isEmpty 不是一个东西”。输出 window 中的每一个错误都会在运行时导致早期形式的异常。这不是“天哪,我添加了一件事,突然出现了一百个错误——那一定是做错了”;错误总是在等待发生
开启 Option Strict 只会强制执行后两项中的任何一项。
我将 Java 程序翻译成 VB.net。程序编译无误。
当我第一次执行程序时,程序在下一行崩溃
If oEnvironMap.isEmpty() Then
表示
System.MissingMemberException : public member 'isEmpty' from 'SortedDictionary(Of String,String)' type is not foundable
其中 oEnvironMap
声明行在后面
Private oEnvironMap = New SortedDictionary(Of String, String)
如果我添加 as
单词,如下面的代码
Private oEnvironMap as SortedDictionary(Of String, String) = New SortedDictionary(Of String, String)
构建应用程序 return 与 oEnvironMap
一起使用的方法有很多错误。
就我个人而言,我认为使用隐式声明来声明 VB.Net 变量是允许的。
我现在发现它不适用于作为字典的复杂数组!
这是 Visual Studio Community 2019 中的错误,我可以与 MSDN 沟通,还是仅仅是个人误解?
我知道这不会回答 'implicit variable' 的问题,但可能有助于解决 OP 的问题。
正如评论所说,.net 中没有针对 SortedDictionary(Of TKey, TValue)
类型的方法您将需要测试 'Count' 属性 - 如果您的对象为 Nothing(在 C# 中为 null),它将抛出异常
或者您可以使用 .net
的 LINQ-函数之一例如
导入 Linq(确保引用 System.Linq.dll
)
Imports System.Linq
并测试你的词典
If Not oEnvironMap.Any() Then
'is empty
end if
VB 中有三个选项与此处相关,您应该了解每个选项的作用。
Option Explicit
实际上是可以允许隐式声明的。它默认是 On
,永远不要变成 Off
。当 Off
时,您可以在代码中引入变量而无需事先声明。当 On
您必须在使用前声明每个变量。
Option Infer
是相当新的,是与 LINQ 一起引入的,以支持匿名类型。当 Off
时,所有变量都必须显式指定其数据类型,或者在允许的情况下,它们将默认为类型 Object
。当On
时,可以通过在声明变量的地方初始化变量来隐式指定变量的类型。无论该表达式的 return 类型是什么,都将为该变量推断类型。默认情况下它是 On
,可能应该保持这种状态,但如果您不使用匿名类型并且不介意显式指定每个变量的类型,则可以将其变为 Off
。成员变量不支持类型推断。
Option Strict
是争论的焦点。默认是Off
,主要是为了方便VB6代码的升级,也是为了让语言对初学者更加宽容。您应该在任何现有项目的属性以及 IDE 选项中将其设置为 On
,以便所有未来项目默认为 On
。当 Off
时,您可以省略任何变量、属性 或方法的任何数据类型规范,除非可以进行类型推断,否则它们将默认为 Object
。您还可以在设置变量或属性或传递方法参数时依赖隐式转换。后期绑定也是允许的,即访问编译器无法确认存在且必须在 运行 时间确认的成员。在几乎所有情况下,这都是不好的。 Option Strict
默认情况下应为 On
,因此您必须始终指定和使用正确的数据类型。在需要后期绑定的极少数情况下,您可以在包含实际需要它的最少代码的文件的文件级别打开 if Off
。
在您的特定情况下,问题是您有 Option Strict Off
,因此您的变量类型为 Object
。这与 Option Infer
无关,因为字段不支持类型推断。编译器不知道它所引用的对象会有哪些成员,所以它可以让你做任何事情。您尝试访问一个成员,但直到 运行 时间才确定。
转向 Option Strict On
,指定该字段的类型,然后仅在您的代码中使用该类型实际具有的成员,这将由编译器强制执行,而不是推迟到 运行 时间.
您可以通过以下多种方式在 VB 中创建变量。我会选择一些基本的东西,比如用一个字符 c
制作一个新字符串,所以在右边我们总是有“一个字符串”
Private s = New String("c"c, 1) 's is Object, compilation fails if Option Strict On even if Option Infer On
Private t As New String("c"c, 1) 't is String, shorthand of below
Private u As String = New String("c"c, 1) 'u is String
Private Sub Blah()
Dim x = New String("c"c, 1) 'x is Object if Option Infer Off, and fails to compile with Option Strict On but succeeds if Off. x is String if Option Infer On and compilation succeeds regardless of Option Strict
Dim y As New String("c"c, 1) 'y is String, shorthand of below
Dim z As String = New String("c"c, 1)
End Sub
区分私有成员变量 s 和局部 Dim 变量 x 可能很重要。
关闭 Option Strict 和 Infer Off,所有这些都将编译,但 s
和 x
将是 Object,intellisense 将只显示 Object 成员。 VB 将在运行时解决问题并将它们视为字符串,但如果您尝试使用 String 上不可用的内容(它仍然是一个字符串,只是“看起来像对象”),您会收到错误消息
在 Option Strict On 和 Infer Off 的情况下,s 和 x 将无法编译,您需要在某处使用“As”以将它们键入为字符串。 Intellisense 将起作用,因为编译器将变量解析为字符串,因为它们已经被 As'd
使用 Option Infer On,您可以编写 Dim x = ...
,因为推断会查看右侧并看到它是一个字符串,然后为您键入 x 作为字符串,但这仅适用于Dim
的局部变量,而不是 class 的成员变量。这意味着使用 Strict On 和 Infer On 你仍然会得到一个编译器错误,但这次只是在 Private s
上,因为它还没有 As
并且 Infer 没有 As
为你
所有这些都与泛型类型无关——任何提到 X(Of...) 的东西——你可以将 New String("c"c, 1)
换成 New Dictionary(Of String, Int)
并体验所有相同的规则
因此你的 vs 的行为是:
Private oEnvironMap = New SortedDictionary(Of String, String)
Strict 关闭,Infer 无关紧要,oEnvironMap 是一个对象,不会发生编译器错误,因为 VB 将其记为“必须在运行时计算出来”。在运行时,结果 isEmpty
不是一个东西 -> 异常
如果你给它一个类型:
Private oEnvironMap As New SortedDictionary(Of String, String)
Private oEnvironMap As SortedDictionary(Of String, String) = New SortedDictionary(Of String, String)
突然间,编译器 知道它是一个字典,并开始在编译时找出所有错误(之前会在运行时发生)。作为编译的一部分,它现在可以告诉您“isEmpty 不是一个东西”。输出 window 中的每一个错误都会在运行时导致早期形式的异常。这不是“天哪,我添加了一件事,突然出现了一百个错误——那一定是做错了”;错误总是在等待发生
开启 Option Strict 只会强制执行后两项中的任何一项。