|Important||This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here. ArchiveDisclaimer|
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 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.
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 the Microsoft Developer Network (MSDN) Web site.
CLS rules apply only to those parts of a type that are exposed outside the defining assembly.
Global static fields and methods are not CLS-compliant.
Characters and casing
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 from the Web site of the Unicode Consortium.
For two identifiers to be considered distinct, they must differ by more than just their case.
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.
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.
All return and parameter types appearing in a type or member signature must be CLS-compliant.
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.
Type and member declarations must not contain types that are less visible or accessible than the type or member being declared.
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.
The individual members of CLS-compliant interfaces and abstract classes must be defined to be CLS-compliant.
Before it accesses any inherited instance data, a constructor must call the base class's constructor.
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.)
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
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.
If either op_Implicit or op_Explicit is overloaded on its return type, an alternate means of providing the conversion must be provided.
Accessibility of overridden methods
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.
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.)
The getter and setter methods that implement the methods of a property are marked with the mdSpecialName identifier in the metadata.
The property and its accessors must all be static, all be virtual, or all be instance.
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
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.
The methods for adding and removing an event must both be present or absent.
Event method metadata
The methods that implement an event must be marked with the mdSpecialName identifier in the metadata.
The accessibility of the methods for adding, removing, and raising an event must be identical.
The methods for adding, removing, and raising an event must all be static, all be virtual, or all be instance.
Event method names
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.
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 and function pointer types are not CLS-compliant.
CLS-compliant interfaces must not require the definition of non-CLS-compliant methods in order to implement them.
CLS-compliant interfaces cannot define static methods, nor can they define fields. They are allowed to define properties, events, and virtual methods.
For reference types, object constructors are only called as part of the creation of an object, and objects are only initialized once.
A CLS-compliant class must inherit from a CLS-compliant class (System.Object is CLS-compliant).
Array elements must be CLS-compliant types.
Arrays must have a fixed number of dimensions that is greater than zero.
All dimensions of an array must have a zero lower bound.
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.
Literal static fields of an enumeration must be the same type as the type of the enumeration itself.
Objects that are thrown must be of type System.Exception or inherit from System.Exception.
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.
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.
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 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.
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.
Types used as constraints on generic parameters must themselves be CLS-compliant.
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.
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.