Ch.01:C – Language Interoperability When we say Language Interoperability, what we really mean by this is that classes written in one language are able to talk directly to classes written in another language. To be more specific we can say that: A class written in one language can be inherited by a class written in another language. Irrespective of the language used, a class can have instances of other classes that have been written in one or more languages as per my previous point. An object written in one language can directly call and make use of methods or properties from another object written in another language. Objects written in different languages can be passed as arguments and return values irrespective of the language the code is written. In the above statements I repeatedly referred to languages without naming any of them, which does not go onto say any programming language that is out there available. I referred to only those languages that are supported by .NET platform and those that have a .NET compiler to compile the code into IL code. You can refer to the previous article in this series to know the list of languages that are supported by .NET framework. You might ask me now that when we can develop everything in one language, why do we need so many languages? By supporting more than one languages, .NET makes it easy for people to start developing .NET based applications instead of asking them to learn everything from the beginning. By supporting multiple languages, .NET removes the restriction of language dependency and allows people to choose their preferred language of development. I can continue to go on giving the benefits of .NET supporting multiple languages, but that is not what we set out to do with this course. How does .NET achieve Language Interoperability? Since developers use a wide variety of tools & technologies, each of them supporting different features and types, it has historically been difficult to ensure language interoperability. However, language compilers & tools that target the CLR (Common Language Runtime) benefit from the runtime's built-in support for language interoperability. For a class to derive from or have instances of other classes, it should have the knowledge about all the data types used by the other classes. This is why strong data typing is so important. Take an example of a method written in VB.NET defined to return an Integer (a data type available in VB.NET). C# does not have any data type of that name. If only the C# compiler knows how to map a VB.NET Integer data type to some known type in C#, the problem will be solved. Common Type System .NET solves this data type mapping problem by using the Common Type System (CTS). CTS defines how types are declared, used and managed in the CLR. The CTS pre-defines data types that are available in IL, so that all language compilers that target the .NET Framework will produce compiled code that is ultimately based on these types. If we get back to our previous example, the IL type Int32 maps exactly to the Visual Basic 2010s Integer, which is actually a 32-bit signed integer. This Int32 has a corresponding data type in C# called int and all the other languages that target .NET framework have it, but with different keywords. We the code from VB.NET or C# or other languages are compiled into IL, they all are simply mapped as Int32. In the same way there is a mapping for all types. In .Net Framework, System.Object is the common base type from where all the other types are derived. IL provides a number of predefined primitive data types. IL makes a strong distinction between value types and reference types. Value types are those where the variable stores its data directly, whereas in case of reference type, variable simply stores the address at which the corresponding data can be found. IL also specifies the manner in which the data is stored for both value and reference types. In case of a value type, the data is stored in stack, where as for reference types they are always stored in an area of memory known as the managed heap. However, if value types are declared as fields within reference types, they will be stored inline on the heap. In the coming chapters, I will cover the stack and the heap and how they work. Also I will cover the list of all built in value types in the coming chapters. Common Language Specification Common Language Specification (CLS) works with the CTS to ensure language interoperability. Different languages provide different set of features which comes in the way of language interoperability. To fully interact with other objects regardless of the language they were implemented in, objects must expose to callers only those features that are common to all the languages that target .NET framework. Common Language Specification, specifies a set of minimum standards that all compilers targeting .NET must support. The CLS was designed to be large enough to include the language constructs that are commonly needed by developers, yet small enough that most languages are able to support it. This does not mean that we are not supposed to write non-CLS code. The restriction of using CLS compliant features applies only to public & protected members of classes & public classes. Within private implementations of the classes, you can have non CLS compliant code, because code in other assemblies cannot access this part of your code anyway and hence does not affect language interoperability. For C# developers, the CLS will not affect your C# code very much because there are very few non CLS compliant features of C#. This means that C# language by itself is CLS compliant to a large extent. Note: It is perfectly acceptable to write non - CLS - compliant code. However, if you do, the compiled IL code is not guaranteed to be fully language interoperable.