Common Language Specification
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 they must interoperate with. For this reason, the Common Language Specification (CLS), which is a set of basic language features needed by many applications, has been defined. The CLS rules define a subset of the Common Type System; that is, all the rules that apply to the common type system apply to the CLS, except where stricter rules are defined in the CLS. The CLS helps enhance and ensure language interoperability by defining a set of features that developers can rely on to be available in a wide variety of languages. The CLS also establishes requirements for CLS compliance; these help you determine whether your managed code conforms to the CLS and to what extent a given tool supports the development of managed code that uses CLS features.
If your component uses only CLS features in the API that it exposes to other code (including derived classes), the component is guaranteed to be accessible from any programming language that supports the CLS. Components that adhere to the CLS rules and use only the features included in the CLS are said to be CLS-compliant components.
Most of the members defined by types in the .NET Framework Class Library Overview are CLS-compliant. However, some types in the class library have one or more members that are not CLS-compliant. These members enable support for language features that are not in the CLS. The types and members that are not CLS-compliant are identified as such in the reference documentation, and in all cases a CLS-compliant alternative is available. For more information about the types in the .NET Framework class library, see the .NET Framework Class Library Reference.
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. In addition, any language construct that makes it impossible to rapidly verify the type safety of code was excluded from the CLS so that all CLS-compliant languages can produce verifiable code if they choose to do so. For more information about verification of type safety, see Compiling MSIL to Native Code.
The following table summarizes the features that are in the CLS and indicates whether the feature applies to both developers and compilers (All) or only compilers. It is intended to be informative, but not comprehensive. For details, see the specification for the Common Language Infrastructure, Partition I, which is available on MSDN at https://msdn.microsoft.com/net/ecma.
Feature | Applies to | Description |
---|---|---|
General |
|
|
Visibility |
All |
CLS rules apply only to those parts of a type that are exposed outside the defining assembly. |
Global members |
All |
Global static fields and methods are not CLS-compliant. |
Naming |
|
|
Characters and casing |
All |
CLS-compliant language compilers must follow the rules of Annex 7 of Technical Report 15 of the Unicode Standard 3.0, which governs the set of characters that can start and be included in identifiers. This standard is available at www.unicode.org/unicode/reports/tr15/tr15-18.html. For two identifiers to be considered distinct, they must differ by more than just their case. |
Keywords |
Compilers |
CLS-compliant language compilers supply a mechanism for referencing identifiers that coincide with keywords. CLS-compliant language compilers provide a mechanism for defining and overriding virtual methods with names that are keywords in the language. |
Uniqueness |
All |
All names within a CLS-compliant scope must be distinct, even if the names are for two different kinds of members, except where the names are identical and resolved through overloading. For example, the CLS does not allow a single type to use the same name for a method and a field. |
Signatures |
All |
All return and parameter types appearing in a type or member signature must be CLS-compliant. |
Types |
|
|
Primitive types |
All |
The .NET Framework class library includes types that correspond to the primitive data types that compilers use. Of these types, the following are CLS-compliant: Byte, Int16, Int32, Int64, Single, Double, Boolean, Char, Decimal, IntPtr, and String. For more information about these types, see the table of types in .NET Framework Class Library Overview. |
Boxed types |
All |
Boxed value types (value types that have been converted to objects) are not part of the CLS. Instead, use System.Object, System.ValueType, or System.Enum, as appropriate. |
Visibility |
All |
Type and member declarations must not contain types that are less visible or accessible than the type or member being declared. |
Interface methods |
Compilers |
CLS-compliant language compilers must have syntax for the situation where a single type implements two interfaces and each of those interfaces requires the definition of a method with the same name and signature. Such methods must be considered distinct and need not have the same implementation. |
Closure |
All |
The individual members of CLS-compliant interfaces and abstract classes must be defined to be CLS-compliant. |
Constructor invocation |
All |
Before it accesses any inherited instance data, a constructor must call the base class's constructor. |
Typed references |
All |
Typed references are not CLS-compliant. (A typed reference is a special construct that contains a reference to an object and a reference to a type. Typed references enable the common language runtime to provide C++-style support for methods that have a variable number of arguments.) |
Type Members |
|
|
Overloading |
All |
Indexed properties, methods, and constructors are allowed to be overloaded; fields and events must not be overloaded. Properties must not be overloaded by type (that is, by the return type of their getter method), but they are allowed to be overloaded with different numbers or types of indexes. Methods are allowed to be overloaded only based on the number and types of their parameters, and in the case of generic methods, the number of their generic parameters. Operator overloading is not in the CLS. However, the CLS provides guidelines about providing useful names (such as Add()) and setting a bit in metadata. Compilers that choose to support operator overloading should follow these guidelines but are not required to do so. |
Uniqueness of overloaded members |
All |
Fields and nested types must be distinct by identifier comparison alone. Methods, properties, and events that have the same name (by identifier comparison) must differ by more than just the return type. |
Conversion operators |
All |
If either op_Implicit or op_Explicit is overloaded on its return type, an alternate means of providing the conversion must be provided. |
Methods |
|
|
Accessibility of overridden methods |
All |
Accessibility must not be changed when overriding inherited methods, except when overriding a method inherited from a different assembly with FamilyOrAssembly accessibility. In this case, the override must have Family accessibility. |
Argument lists |
All |
The only calling convention supported by the CLS is the standard managed calling convention; variable length argument lists are not allowed. (Use the ParamArray keyword in Microsoft Visual Basic and the params keyword in C# for variable number of arguments support.) |
Properties |
|
|
Accessor metadata |
Compilers |
The getter and setter methods that implement the methods of a property are marked with the mdSpecialName identifier in the metadata. |
Modifiers |
All |
The property and its accessors must all be static, all be virtual, or all be instance. |
Accessor names |
All |
Properties must follow specific naming patterns. For a property called Name, the getter method, if defined, will be called get_Name and the setter method, if defined, will be called set_Name. |
Return type and arguments |
All |
The type of the property is the return type of the getter and the type of the last argument of the setter. The types of the parameters of the property are the types of the parameters to the getter and the types of all but the final parameter of the setter. All these types must be CLS-compliant and cannot be managed pointers; they must not be passed by reference. |
Events |
|
|
Event methods |
All |
The methods for adding and removing an event must both be present or absent. |
Event method metadata |
Compilers |
The methods that implement an event must be marked with the mdSpecialName identifier in the metadata. |
Accessor accessibility |
All |
The accessibility of the methods for adding, removing, and raising an event must be identical. |
Modifiers |
All |
The methods for adding, removing, and raising an event must all be static, all be virtual, or all be instance. |
Event method names |
All |
Events must follow specific naming patterns. For an event named MyEvent, the add method, if defined, will be named add_MyEvent, the remove method, if defined, will be named remove_MyEvent, and the raise method will be named raise_MyEvent. |
Arguments |
All |
The methods for adding and removing an event must each take one parameter whose type defines the type of the event, and that type must be derived from System.Delegate. |
Pointer Types |
|
|
Pointers |
All |
Pointer types and function pointer types are not CLS-compliant. |
Interfaces |
|
|
Member signatures |
All |
CLS-compliant interfaces must not require the definition of non-CLS-compliant methods in order to implement them. |
Member modifiers |
All |
CLS-compliant interfaces cannot define static methods, nor can they define fields. They are allowed to define properties, events, and virtual methods. |
Reference Types |
|
|
Constructor invocation |
All |
For reference types, object constructors are only called as part of the creation of an object, and objects are only initialized once. |
Class Types |
|
|
Inheritance |
All |
A CLS-compliant class must inherit from a CLS-compliant class (System.Object is CLS-compliant). |
Arrays1 |
|
|
Element types |
All |
Array elements must be CLS-compliant types. |
Dimensions |
All |
Arrays must have a fixed number of dimensions, greater than zero. |
Bounds |
All |
All dimensions of an array must have a zero lower bound. |
Enumerations |
|
|
Underlying type |
All |
The underlying type of an enumeration must be a built-in CLS integer type (Byte, Int16, Int32, or Int64). |
FlagsAttribute |
Compilers |
The presence of the System.FlagsAttribute custom attribute on the definition of an enumeration indicates that the enumeration should be treated as a set of bit fields (flags), and the absence of this attribute indicates the type should be viewed as a group of enumerated constants. It is recommended that languages use either the FlagsAttribute or language-specific syntax for distinguishing between these two types of enumerations. |
Field members |
All |
Literal static fields of an enumeration must be the same type as the type of the enumeration itself. |
Exceptions |
|
|
Inheritance |
All |
Objects that are thrown must be of type System.Exception or inherit from System.Exception. |
Custom Attributes |
|
|
Value encodings |
Compilers |
CLS-compliant compilers are required to deal with only a subset of the encodings of custom attributes (the representation of custom attributes in metadata). The only types that are permitted to appear in these encodings are: System.Type, System.String, System.Char, System.Boolean, System.Byte, System.Int16, System.Int32, System.Int64, System.Single, System.Double, and any enumeration type based on a CLS-compliant base integer type. |
Metadata |
|
|
CLS compliance |
All |
Types whose CLS compliance differs from that of the assembly in which they are defined must be so marked with the System.CLSCompliantAttribute. Similarly, members whose CLS compliance differs from that of their type must also be marked. If a member or type is marked as not CLS-compliant, a CLS-compliant alternative must be provided. |
Generics |
||
Type names |
Compilers |
The name of a generic type must encode the number of type parameters declared on the type. The name of a nested generic type must encode the number of type parameters newly introduced to the type. |
Nested types |
Compilers |
Nested types must have at least as many generic parameters as the enclosing type. Generic parameters in a nested type correspond by position to the generic parameters in its enclosing type. |
Constraints |
All |
A generic type must declare sufficient constraints to guarantee that any constraints on the base type or interfaces are satisfied by the generic type constraints. |
Constraint types |
All |
Types used as constraints on generic parameters must themselves be CLS-compliant. |
Member signatures |
All |
The visibility and accessibility of members (including nested types) in an instantiated generic type is considered to be scoped to the specific instantiation rather than the generic type declaration as a whole. |
Generic methods |
All |
For each abstract or virtual generic method, there must be a default concrete (non-abstract) implementation |
1. Jagged arrays — that is, arrays of arrays — are CLS-compliant. In the .NET Framework version 1.0, the C# compiler mistakenly reports that they are not.
See Also
Concepts
Language Interoperability Overview