schlebe
schlebe

Reputation: 3715

In VB.NET, is IMPLICIT variable declaration (= New) allowed for all types of variable?

I translated a Java program to VB.net. The program has been built without error.

When I execute the program for first time, the program crashes on following line

If oEnvironMap.isEmpty() Then

indicating that

System.MissingMemberException : public member 'isEmpty' from 'SortedDictionary(Of String,String)' type is not foundable

where oEnvironMap declaration line is following

Private oEnvironMap = New SortedDictionary(Of String, String)

If I add as word as in following code

Private oEnvironMap as SortedDictionary(Of String, String) = New SortedDictionary(Of String, String)

building application return a lot of errors on methods used with oEnvironMap.

Personnally, I thought that declaring a VB.Net variable using implicit declaration is allowed.

I now see that is not working for complex array as Dictionary !

Is that a bug in Visual Studio Community 2019 that I can communicate to MSDN or it is simply a personal misunderstanding ?

Upvotes: 0

Views: 892

Answers (3)

Caius Jard
Caius Jard

Reputation: 74660

Here are various ways you can make a variable in VB. I'll pick on something basic such as making a new string out of a single char c so on the right hand side we always have "a string"

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

It's perhaps important to draw a distinction between the Private member variable s and the local Dim'd variable x.

With Option Strict Off and Infer Off, all these will compile, but s and x will be Object, intellisense will only show you Object members. VB will figure things out at runtime and treat them as strings but you get an error if you try to use things that aren't available on String (it's still a string, just "looks like Object")

With Option Strict On and Infer Off, s and x will fail to compile, and you need to use "As" somewhere to get them typed as a string. Intellisense will then work because the compiler resolves the variables to strings because they've been As'd

With Option Infer On, you can get away with writing Dim x = ... because the infer will look at the right hand side and see it's a string, and type x as string for you, but it's only true for Dim'd local variables, not class member variables. This means that having Strict On and Infer On you still get a compiler error but this time only on the Private s because it hasn't been As'd and Infer didn't As it for you


And all this is unrelated to generic types - anything that mentions X(Of...) - you can swap out the New String("c"c, 1) for New Dictionary(Of String, Int) and experience all the same rules


The behavior of your vs is thus:

Private oEnvironMap = New SortedDictionary(Of String, String)

Strict is off, Infer is irrelevant, oEnvironMap is an Object and no compiler errors will occur because VB puts it down as "gotta figure that one out at runtime". At runtime, turns out isEmpty ain't a thing -> exception

If you give it a type with either:

Private oEnvironMap As New SortedDictionary(Of String, String)
Private oEnvironMap As SortedDictionary(Of String, String) = New SortedDictionary(Of String, String)

Suddenly the compiler knows it's a dictionary, and starts figuring out all the errors (that would have happened at runtime before) now at compile time instead. It can now tell you "isEmpty ain't a thing" as part of the compilation. Every single one of those error in the output window is something that would have caused an exception at runtime with the earlier form. This isn't a "OMG I added one thing and suddenly a hundred errors appeared - that must have been the wrong thing to do"; the errors were always waiting to happen

Turning Option Strict On would have simply enforced that you did either of these latter two.

Upvotes: 3

jmcilhinney
jmcilhinney

Reputation: 54457

There are three options in VB that are relevant here and you should understand what each does.

Option Explicit is actually the one that can allow implicit declarations. It is On by default and should NEVER be turned Off. When Off, you can introduce a variable in your code without prior declaration. When On you MUST declare every variable before use.

Option Infer is fairly new and was introduced with LINQ to support anonymous types. When Off, all variables must have their data types specified explicitly or, where it is allowed, they will default to type Object. When On, the type of a variable can be specified implicitly by initialising the variable where it is declared. Whatever the return type of that expression will be type inferred for the variable. It is On by default and should probably be left that way but it can be turned Off if you won't be using anonymous types and don't mind explicitly specifying the type of every variable. Type inference is not supported for member variables.

Option Strict is a big bone of contention. It is Off by default, mainly to facilitate upgrade of VB6 code but also to make the language more forgiving for beginners. You should turn it On in the properties of any existing projects and also in the IDE options so that it will be On by default for all future projects. When Off, you are permitted to omit any data type specification for any variable, property or method and they will default to Object unless type inference is possible. You are also permitted to rely on implicit conversions when setting variables or properties or passing method arguments. Late binding is also permitted, i.e. accessing members that the compiler cannot confirm exist and must be confirmed at run time. That is all bad in almost every situation. Option Strict should be On by default so you are forced to always specify and use the correct data type. In the very rare situations where late binding is required, you can turn if Off at the file level in the minimum of files containing the minimum of code that actually requires it.

In your particular case, the issue is that you have Option Strict Off and so your variable is type Object. That regardless of Option Infer because type inference is not supported for fields. The compiler doesn't know what members the object it refers to will have so it lets you do anything. You try to access a member that doesn't but that is determined until run time.

Turn Option Strict On, specify the type of that field and then only use members in your code that that type actually has, which will be enforced by the compiler instead of being deferred until run time.

Upvotes: 0

dba
dba

Reputation: 1185

I know this will not answer the question of 'implicit variable', but may help to solve the problem of OP.

As the comments say, there is no such Method in .net for the type SortedDictionary(Of TKey, TValue)

You will need to test the 'Count' Property - it will throw Exception if your object is Nothing (null in C#)

Or you could use one of the LINQ-Functions of .net

e.g.
import Linq (make sure System.Linq.dll is referenced)

Imports System.Linq

and test your Dictionary

If Not oEnvironMap.Any() Then
  'is empty
end if

Upvotes: -1

Related Questions