How serious is BC42020 in an upgraded VB .Net project? - vb.net

Consider the following line of code which used to compile without warnings.
Public SetUpDone = False
After upgrading a project to Visual Studio 2017 from Visual Studio 2005 over a hundred of these BC42020 warnings exist. The MSDN description of the warning simply states that the variable defaults to type object. I don't have a good idea of the seriousness of this type of warning. The debugger indicates that the code executes as I expect. Is it merely a performance type of issue?
Secondly, I thought that Visual Basic supported some form of Type Inference so I'm not clear about why it wouldn't be able to deduce that the type should be Bool.
Another example is the following where the function returns a String
Dim dayTxt = " " & GetTextFromIni("General", "Var50")
I would have thought that type inference would work here and deduce that dayTxt is a String.

This:
Public SetUpDone = False
Is equivalent to this:
Public SetUpDone As Object = False
As suggested, type inference is only for local variables, not fields. With Option Infer On, this inside a method:
Dim SetUpDone = False
would indeed be equivalent to this:
Dim SetUpDone As Boolean = False
There are a couple of issues with the code as you have it. Firstly, it means that every use of that False value requires unboxing which makes your code slower. That's the case for any value types, i.e. structures. Value types are normally stored on the stack but, when boxed, are stored on the heap.
Secondly, it means that any member access will require late binding. That's not an issue for Boolean values because they have no members of interest anyway but if it was, say, a DateTime then the IDE would never provide Intellisense for that type because al it would see would be type Object and the existence of the specified member would have to be confirmed at run time, making the code less efficient again.
Thirdly, it means that the compiler can never confirm that you're passing the correct type as a method argument. For instance, if you have a method with a Boolean parameter, the compiler won't know that you're passing a Boolean if you pass that field because it's type Object. That also means that if you pass some other Object variable that doesn't contain a Boolean, the compiler can't warn you.
As suggested, you should turn Option Strict On in the project properties. That will flag every instance of you're not specifying the appropriate type for something. Fixing those errors will, at the very least, make your code a bit more efficient. It may even draw your attention to situations where exceptions will or could be thrown at run time. Having Option Strict On enforces strict typing so it makes you think more about the types you're using. Even if you're conscientious about that with Option Strict Off, you can still make mistakes that Option Strict On will prevent.

Related

Strict Properties Without Option Strict On

When Option Strict is turned Off, which is the default for my application, VB will automatically convert the value when property is String. It appears to call the toString() of the incoming value's Object. I believe casting will work for any property that can be safely casted (eg integer to double). I want the properties to behave in a strict manner, in that the Type passed MUST match the type on the declared property.
Is there a way to make Objects Properties Strict at the Object level without having to resort to the Option Strict On configuration on?
For example:
Option Strict Off
Class TestObj
Private _foo As String
Public Property Foo as String
Get
Return _foo
End Get
Set(v As String)
console.write(String.format("v = <{0}> {1}", v.GetType().FullName, v))
_foo = v
End Set
End Property
End Class
Dim o as new TestObj()
o.Foo = "some_str"
o.Foo = 1234
o.Foo = DateTime.now()
In the above case, all values are converted to Strings at arrival to the setter:
v = <System.String> some_str
v = <System.String> 1234
v = <System.String> 7/7/2022 8:22:49 PM
I am aware of DynamicObject and ability to tightly control setters like Python's __setattr__ but this breaks autocomplete functionality in editors as it would preclude defining properties on the class to get the functionality.
I strongly agree with the commenters that Option Explicit On and Option Strict On are simply a must - as the default settings of Visual Studio for new VB projects as well as for each project within the solution(s) you took over.
I my opinion one has to invest first some effort into clean-up work when taking over legacy solutions including
Add an ".editorconfig" if there isn't any
Convert the projects to SDK projects where possible
Go through the code and
format the code to your liking using the current naming convention where possible
correct/complement/remove/translate-to-English the documentation comments
add some //TODO: - comments where refactoring is needed wherever you notice a code repetition, repeated property access, huge methods that needs to be split into smaller parts, if-not-condition-then-else that needs to be reverted etc. but don't code it yet - these refactorings could introduce some bugs, we need to finish the next step first.
put every top-level type in its own file (except overloaded generic types of the same name) and make sure the type name matches the file name
Go through the unit tests and fix them, remove unnecessary ones and complement the missing ones.
Change all projects to Option Explicit On, Option Strict On and Option Compare Binary (use explicit StringComparer.OrdinalIgnoreCase / StringComparer.InvariantCultureIgnoreCase where needed). (Option Infer On or Off, what you prefer). If you hate to have 1000s of errors, add an Option Strict Off on top of each VB file which you later removed again file by file, otherwise do a bulk mutation.
Fix all compile errors (per file or bulk mutation)
Run unit tests, fix code of failing tests (repeat this after each of the following steps)
Update the .NET framework version if possible (e.g. to current or .NET 4.8)
Update the NuGet packages
Do all the previously tagged refactorings
Enable the analyzer warnings
Fix all the warnings and infos or suppress them, individually or in the project file by adding the according entry to the <NoWarn> element.
Start implementing the changes why you originally cloned the repository...
Of course that comes with a price but not doing it also has its price - I'm certain you are going to find dozens of little mistakes in the original code during the process of going Strict. And the time one spends formatting the code files is not just wasted time neither as in the process one also learns to understand the code...

Turning on Option Strict - Pitfalls?

I'm turning On Option Strict on all project in my newly inherited VB.NET application. I'm mostly adding alot of CStr, CBool, CType statements to get rid of all the compile errors.
Dim x As String = someObject
dim val As SomeEnumType = 1
becomes
Dim x As String = CStr(someObject) ' Not .ToString() because someObject could be Nothing
Dim val As SomeEnumType = CType(1, SomeEnumType)
etc.
I'm doing everything pretty much by hand one error at a time and have a test application to test the Nothing, ... bordercases.
But is it possible I'm missing something that is going to generate exceptions at runtime?
And what kind of code is being generated due to Option Strict? Is it just some conversions that are going to be added or does OptionStrict do other things aswell?
Option Strict On does not generate any extra code, it merely tells the compiler to generate errors when your vb.net statements are relying on implicit type conversions. Like assigning an object to a string. What you've written in your snippet is exactly what the compiler does with Option Strict Off so no extra code is generated by your type conversion operators.
But of course, there's always a non-zero chance that you use the wrong conversion and break the existing code. You'll have to do what's always required when you make changes to code, you'll have to re-test it.

Should I explicitly declare my variables in VB6

I'm writing some code in Visual Basic 6 and I have noticed that I don't even need to declare variables for things to work.
The following (explicit declaration):
Dim foo As String
foo = "Bar"
Seems to work just as well as this (implicit declaration):
Dim foo
foo = "Bar"
Or this (no declaration):
foo = "Bar"
I know in C# I need to declare a variable before I use it, and that implicit and explicit declarations are both acceptable. I also know that in Python, you don't declare your variables at all before you use them.
In regards to Visual Basic 6 (and by extension VBA) which is proper?
Thanks
It's a good HABIT.
There is a VB option called Option Explicit. With that set to ON, then VB forces you to declare a variable before you use it: no more
foo = "Bar"
That helps with mistyping the variable name later in your code... without that, you can typso the variable name, your program compiles but won't work, and it's HARD to dig that out.
In Tools/Options, Editor tab, check the Require Variable Declaration checkbox. This will automatically add Option Explicit to every new code module.
I would say this is more than a best practice; I think of it as a requirement for programmer sanity. The setting is persistent; once set, it stays enabled. Microsoft made it an option because some older versions of VB didn't have the feature, which also explains why it was disabled by default.
Should I explicitly declare my variables in VB6?
Yes. Why?
Not just because it is a good habit or it is a must but because of only one main reason which I have mentioned in this post as well.
VB defaults the variable to being type Variant. A Variant type
variable can hold any kind of data from strings, to integers, to long
integers, to dates, to currency etc. By default “Variants” are the
“slowest” type of variables.
AND
As I mentioned earlier, If you do not specify the type of the
variable, VB defaults the variable to being type Variant. And you
wouldn’t want that as it would slow down your code as the VB Compiler
takes time to decide on what kind of variable you are using. Variants
should also be avoided as they are responsible for causing possible
“Type Mismatch Errors”.
Topic: To ‘Err’ is Human (See Point 3)
Link: http://siddharthrout.wordpress.com/2011/08/01/to-err-is-human/
The above link also covers other parts related to coding that one can/should take care of.
HTH
I highly reccomend that you always declare your variables. This can be forced by setting Option Explicit in each code module. You can let VB6 do that automatically for you by going to Tools->Options, in the Editor tab check Require variable declaration.
If you don't use Option Explicit, then a variable will be automatically created for you each time you reference a previously unknown variable name. This is a very dangerous behavior, because if you mistype a variable name, an empty variable will be created for you, causing unexpected behavior of your code.
You don't have to declare the type of your variables but I would also recommend that you do that. The default type of a variable is Variant, which has a small performance overhead and create some problems if you are creating COM objects for use by C++ or C# (if anybody does that anymore).

Is it good practice to define "what my variable will be"?

So I have this:
Dim aBoolean As Boolean = True
Will it make any difference to just do this?
Dim aBoolean = True
In other languages, I believe it was a good practice to also define the type of variable it would be, for performance or something. I am not entirely sure with VB.NET.
Thanks.
It depends. Explicitly defining the variable can improve readability, but I don't think it's always necessary. (To be clear, it has nothing to do with the actual functionality of your code).
In this specific example, you follow the declaration with a Boolean assignment of True, so it's already crystal clear that aBoolean is actually a Boolean when it is declared. The As Boolean syntax is not as necessary in this scenario.
Other cases may not be so clear. If the declaration was followed by the result of a function call, for example, it might be more clear to explicitly declare that the variable is a Boolean. e.g.
Dim aBoolean As Boolean = TestValidityOfObject(o)
As long as you have Option Infer turned on, it won't make a bit of difference. The second line is just a syntactic abbreviation for the first. At that point, it's up to your style preference as to which you should use.
Before type inference, there were performance issues when not declaring the type, but that's no longer an issue; due to type inference the variable will be of type Boolean whether you declare it or not.
Declaring the type can help the compiler catch errors sooner, and will often give you better Intellisense.
You're using what's called "type inference". This is where the compiler figures out at compile time what the type on the right side of the assignment is and uses that as the type of the variable.
This is, in general, a safe and convenient feature. However, there are a couple of things to keep in mind:
You must have Option Infer on; otherwise, the compiler doesn't do type inference and, depending on your setting for Option Strict, instead either gives you a compile time error (Option Strict On) or types your variable as Object and uses late binding everywhere. This is Pure Evil. (Option Strict Off)
In your particular case, there's no way for the compiler to mess up. HOWEVER, it's possible to use type inference in such a way as to change the semantics of your code:
For instance...
Dim myClass as MyBaseClass = New SubClass()
This is perfectly legal; we're typing the variable as a base class and assigning a value to it that represents an instance of a subclass. Nothing special. However, if we switch to type inference by just removing the type declaration...
Dim myClass = New SubClass()
Type inference will now see myClass as a SubClass instead of MyBaseClass. This might seem obvious, but the point is that you should be aware of what it's doing.
For more information and long-winded discussion about using type inference, see this question. While that question is targeted at C#, the only real difference is the first item that I listed above. Everything else is conceptually the same.

VB.Net code optimization?

I would like to ask humbly to those vb.net experts out there regarding optimization of the code. My example here is
a.
Dim lblEventCategory = CType(Me.gvSpecialEvent.Rows(e.NewEditIndex).FindControl("lblEventCategory"), Label)
b.
Dim lblEventCategory As Label = CType(Me.gvSpecialEvent.Rows(e.NewEditIndex).FindControl("lblEventCategory"), Label)
Which of the two is more efficient is it letter A? or letter B?
Can somebody help me understand these codes?
Thanks in advance
if we are talking .Net 3.5 than what 1800 INFORMATION says is not true since type inference will take place and the compiler will infer the type and hence be typesafe.
so in .Net 3.5 a and B are the same.
In Visual studio 2008 just turn Option Infer On or Off to see the difference.
Before .Net 3.5 no type inference will take place and it will use the variant type or rather the object type.
So in pre.Net 3.5 A and B are not the same.
In .NET 3.5 Dim x = value is the same as C# var x = value; The compiler will infer the type so both are equal at runtime.
The first one defines the variable lblEventCategory as a Variant type. This is generally worse than the second where you use an explicit type. The Variant type is a kind of "catch all" that can safely hold any type of variable, but you lose any and all type safety and warnings that the compiler might have been able to give you. Also a Variant type uses more memory and will be slower at run time because of the conversions that need to be performed on it.
Additionally, method calls will be "late bound" - this means that the calls to those methods will not be resolved until runtime, when the type of the variable is known, the call is then made by name. This is typically astronomically slower than if you use the explicit type where the call can be made "early bound" (i.e., at compile time).
On the other hand, Variant types do have their place. They are useful in OLE automation (COM) programming, if you are interacting with a language like VBScript that only supports variant types. In that situation, you may be wise to wrap the calls into the late-bound code so that the Variant type is converted to and from the correct type at the boundary of the call.