Share via


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 Managed Execution Process.

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.

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 from the Web site of the Unicode Consortium.

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 the .NET Framework Class Library.

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 that is 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

Other Resources

Cross-Language Interoperability