If you've been building COM components for a while, you know that one of the great promises of COM is that it is language-independent. If you build a COM component in C++, you can call it from VB, and vice versa. However, to reach that point, your code had to be compiled to a COM standard. Much of this was hidden from the VB developer, but your component had to implement the IUnknown and IDispatch interfaces. Without these interfaces, they would not have been true COM components.
Now, however, the CLR gives you much better language interoperability. Not only can you inherit classes from one PE written in language A and use them in language B, but debugging now works across components in multiple languages. This way, you can step through the code in a PE written in C# and jump to the base class that was written in VB.NET. In addition, you can raise an error (now called an exception) in one language and have it handled by a component in another language. This is significant because now developers can write in the language with which they are most comfortable, and be assured that others writing in different languages will be able to easily use their components.
This all sounds great, and you are probably getting excited about the possibilities. There is a catch, however: To make use of this great cross-language interoperability, you must stick to only those data types and functions common to all the languages. If you're wondering just how you do that, the good news is that Microsoft has already thought about this issue and set out a standard called the Common Language Specification, or CLS. If you stick with the CLS, you can be confident that you will have complete interoperability with others programming to the CLS, no matter what languages are being used. Not very creatively, components that expose only CLS features are called CLS-compliant components.
To write CLS-compliant components, you must stick to the CLS in these key areas:
The public class definitions must include only CLS types.
The definitions of public members of the public classes must be CLS types.
The definitions of members that are accessible to subclasses must be CLS types.
The parameters of public methods in public classes must be CLS types.
The parameters of methods that are accessible to subclasses must be CLS types.
These rules talk a lot about definitions and parameters for public classes and methods. You are free to use non-CLS types in private classes, private methods, and local variables. Even if you have a public class that you want to be CLS-compliant, the implementation code inside that class does not have to be CLS-compliant; as long as the definition is compliant, you are safe.
The CLS is still in flux, but the basics are well established.