Language interoperability is the ability of code to interact with code that is written using a different programming language. Language interoperability can help maximize code reuse and, therefore, improve the efficiency of the development process.
Because developers use a wide variety of tools and technologies, each of which might support different features and types, it has historically been difficult to ensure language interoperability. However, language compilers and tools that target the common language runtime benefit from the runtime's built-in support for language interoperability.
The common language runtime provides the necessary foundation for language interoperability by specifying and enforcing a common type system and by providing metadata. Because all languages targeting the runtime follow the common type system rules for defining and using types, the usage of types is consistent across languages. Metadata enables language interoperability by defining a uniform mechanism for storing and retrieving information about types. Compilers store type information as metadata, and the common language runtime uses this information to provide services during execution; the runtime can manage the execution of multilanguage applications because all type information is stored and retrieved in the same way, regardless of the language the code was written in.
Managed code benefits from the runtime's support for language interoperability in the following ways:
Even though the runtime provides all managed code with support for executing in a multilanguage environment, there is no guarantee that the functionality of the types you create can be fully used by the programming languages that other developers use. This is primarily because each language compiler targeting the runtime uses the type system and metadata to support its own unique set of language features. In cases where you do not know what language the calling code will be written in, you are unlikely to know whether the features your component exposes are accessible to the caller. For example, if your language of choice provides support for unsigned integers, you might design a method with a parameter of type UInt32; but from a language that has no notion of unsigned integers, that method would be unusable.