Software Development optimize

Visual Studio compiler options, Part 2: Option Strict

Compiler options are project-level settings that determine how the compiler behaves when it compiles your code. In this post, Daryl Lucas discusses Option Strict.
This is the second in a series on setting compiler options for Visual Studio VB.NET projects, versions 2005-2010. You can access the first piece here. Compiler options are project-level settings that determine how the compiler behaves when it compiles your code. You view and set compiler options in the Compile tab of the project properties sheet, as shown in Figure A. In this second part, I will discuss Option Strict.

Figure A

What it means

Option Strict is a single switch, On or Off. It determines whether VB.NET requires type declarations and puts certain restrictions on implicit conversions. In Visual Studio 2005 and 2008, it's pretty straightforward; with 2010, it gets a little more complicated. Here's a summary of how the compiler behaves when Option Strict is set to On:

  1. Requires type declarations for all variables, constants, routine parameters, and function return values, regardless of scope, unless: In 2010, Option Infer is set to On, in which case type declarations are required only for routine parameters, function return values, and variables outside of local scope.
  2. Disallows late binding.
  3. In 2010, disallows implicit conversions to Object.

We'll discuss Option Infer lightly here to keep things clear, but will go into more detail on it in Part 3.

Type declarations

In VB, a type declaration is simply an As clause, whereby you specify the data type. Visual Basic is a weakly-typed language, so unless you tell VS otherwise, it will let you code merrily along without declaring types, as I've done here:

Dim MysteryVariable = 22205-7509

What kind of data does my mystery variable contain? Is it a number, a string, or something else? It's not clear, and by setting Option Strict to Off, you're saying that it doesn't matter. If the compiler decides that it's a number, it's fine with me. And if it decides that it's a string, that's fine with me too. And decide it will-it will make its best guess, and store it that way. This is called implicit typing, or a type inference; the compiler infers from the data what the type is. This is how VB.NET behaves with Option Strict set to Off.

Setting Option Strict to On forces you to declare variable types before using them, like so:

Dim PostalCode As String = "22205-7509"

Now the compiler is not allowed to decide what it is. I've told it. It's a String.

As mentioned above, VS 2010 lets you relax this restriction substantially by turning on Option Infer. Option Strict = On in VS 2005 and 2008 is exactly equivalent to Option Strict = On + Option Infer = Off in 2010. With Option Infer = On, the compiler behaves as if Option Strict = Off for all variables and constants within routines. In 2012, with Option Infer set to Off, "Dim MysteryVariable = 22205-7509" is perfectly legal within any routine.

Another way of describing this restriction (and the way it is explained in MSDN) is to say that it restricts conversions to widening conversions. This simply means that the compiler will let you stick a small variable into a big variable, but not the other way around, for hopefully obvious reasons. The following (widening conversion) is allowed:

Dim SmallNumber As Integer = 1

Dim BigNumber As Long = 2

BigNumber = SmallNumber

The following (narrowing conversion) is not:

Dim SmallNumber As Integer = 1

Dim BigNumber As Long = 2

SmallNumber = BigNumber

Without this restriction, every variable starts out as an Object, making potentially every assignment into a narrowing conversion, where data loss can easily occur.

This restriction corresponds to the warning configuration named, "Implicit conversion" (see Figure A). When Option Strict is set to On, "Implicit conversion" is set to Error.

Late binding

Late binding refers to the use of a property or method of a variable whose type is Object. In other words, it's when you assume you know what the variable is when you really can't guarantee being right. Here is an example of a late-bound call (on MysteryVariable):

Dim MysteryVariable As Object = "22205-7509"

Dim MysteryVariableLength As Integer

MysteryVariableLength = MysteryVariable.Length

MysteryVariable is an Object, which means that it doesn't contain the data "22205-7509", it merely holds a pointer to the data. Thus, the data's type (string, integer, or whatever) is unknown at compile time. There is therefore no way for the compiler to know whether MysteryVariable will even have a Length property. So, when Option Strict is set to On, the compiler will not let you code it that way. It wants to know whether MysteryVariable has such a property before it will let you write that line. Option Strict = On means no late binding is allowed.

This restriction corresponds to the warning configuration named "Late binding; call could fail at runtime" (see Figure A). When Option Strict is set to On, "Late binding; call could fail at runtime" is set to Error.

Implicit conversions to Object

An implicit conversion to Object occurs whenever the compiler can't tell whether a variable is anything but an Object. This restriction (as part of Option Strict) only applies to VS 2010, but mainly to deal with things when Option Infer is Off, since that's when you can have variables without a type declaration being implicitly converted to Object.

This restriction corresponds to the warning configuration named "Implicit type; object assumed." When Option Strict is set to On, "Implicit type; object assumed" is set to Error.

One final point: Option Strict = On implies variable declarations, so if Option Strict is On, so is Option Explicit.

Why it's important

The chief hazard of skipping type declaration is unpredictable behavior. When variables have no explicit type, the runtime has to infer their type, which means that their type will be determined by the values they contain. With values like "22205-7509", it's going to have to make a compiler's version of an educated guess. It could represent a postal code or an equation, or maybe even a range, but in any case, you have no way of knowing ahead of time how the compiler will rule on this. It's going to make up its mind when it gets the data. And if it decides that the value is a string, it will cast the value as such and return "22205-7509". If it decides that it's an equation, it will subtract 7,509 from 22,205 and return 14,696. It's hard to imagine a program that would want unpredictability like that-unless the whole point of the program were to output unpredictable results!

Problems like this can easily hide behind little subtleties. In the following two lines, the compiler will cast the first as a string and the second as an integer, all depending on whether you use quotation marks:

Dim PostalCode1 = "22205-7509"
		
0 comments