Prior to .NET, interoperating with code written in other languages was challenging. There were pretty much two options for reusing functionality developed in other languages: COM interfaces or DLLs with exported C functions.
Visual Basic is built on top of the CLR. As such it interoperates with code written in other .NET languages. It's even able to derive from a class written in another language. To support this type of functionality, the CLR relies on a common way of representing types, as well as rich metadata that can describe these types.
Each programming language seems to bring its own island of data types with it. To help resolve this problem, C, an operating-system-level implementation language, became the lowest common denominator for interfacing between programs written in multiple languages. An exported function written in C that exposes simple C data types can be consumed by a variety of other programming languages. In fact, the Windows API is exposed for .NET developers as a set of C functions. Note this changes for those building Metro applications, but this does not change the value of the common type system (CTS) across .NET.
Unfortunately, to access a C interface, you must explicitly map C data types to a language's native data types. This is not only cumbersome, but also error prone due to the complexity. Accidentally mapping a variable declared as Long to lpBuffer wouldn't generate any compilation errors, but ...