I remember a line from an old science fiction movie called "The Black Hole" where a little robot says, "You cannot pour a quart into a pint. If a pint holds a pint, it is doing the best that it can." That's essentially the idea behind the difference between widening and narrowing type conversions. A widening conversion is pouring a pint into a quart. A narrowing conversion is the opposite and the problem is that some of whatever is in the quart can spill on the floor.
VB.NET keeps track of whether a conversion is widening or narrowing and since VB.NET 2005, you have been able to use the compiler option ...
Option Strict On
... to disallow any narrowing conversion. According to Microsoft these are the widening conversions for standard data types:
Byte --> Byte, Short, Integer, Long, Decimal, Single, Double
Short --> Short, Integer, Long, Decimal, Single, Double
Integer --> Integer, Long, Decimal, Single, Double
Long --> Long, Decimal, Single, Double
Decimal --> Decimal, Single, Double
Single --> Single, Double
Double --> Double
Any enumerated type --> Its underlying integer type and any type to which it will widen
Char --> Char, String
Any type --> Object, any interface that it implements
Any derived type --> Any base type from which it is derived
Nothing --> Any data type or object type
The default for Option Strict is "Off" mainly for backward compatibility. Most authorities recommend that you turn it on. To do that, place Option Strict On at the top of your code, before any other source code statements. If you turn Option Strict and Option Explicit off, then you can write programs with variables that behave a little like the old VB6 "variant" type. Microsoft calls this "typeless programming" and says it can lead to errors and inefficient code.
The Different Ways Data Type Conversion Can Happen
The first, and probably most common way that data type conversion can happen is implicit conversions. This is just a word that means, "the compiler noticed that you needed one, so it did it for you".
If you code ...
Dim a as Integer = 10 Dim b as String b = a
... your code will include an implicit data type conversion from Integer to String. (This is also an example of a widening conversion.)
Explicit conversion uses a VB.NET supplied conversion keyword. You can use DirectCast, TryCast and a whole group of functions that begin with the letter "C" -- for example CDbl (convert to the Double type) and CBool (convert to a Boolean type). You can't convert anything to anything because sometimes, a conversion just doesn't make sense. For example, only String and Object can be converted to Char. Each conversion has specific rules. One benefit of these explicit conversions is that they are "localization aware". A Date, for example, will appear in the format specified in the location specified.