CLI - The Common Language Infrastructure (CLI) provides a specification for executable code and the
execution environment (the Virtual Execution System) in which it runs. Executable code is
presented to the VES as modules. A module is a single file containing executable content.
CTS - The Common Type System (CTS)—The CTS provides a rich type system that
supports the types and operations found in many programming languages.
VES - The Virtual Execution System (VES)—The VES implements and enforces the CTS
model. The VES is responsible for loading and running programs written for the CLI.
It provides the services needed to execute managed code and data, using the metadata
to connect separately generated modules together at runtime (late binding).
CLS - The Common Language Specification (CLS)—The CLS is an agreement between
language designers and framework (that is, class library) designers. It specifies a
subset of the CTS and a set of usage conventions.
Metadata—The CLI uses metadata to describe and reference the types defined by the
CTS. Metadata is stored (that is, persisted) in a way that is independent of any
particular programming language. Thus, metadata provides a common interchange
mechanism for use between tools (such as compilers and debuggers) that manipulate
programs, as well as between these tools and the VES
CTS :
Types describe values. Any value described by a type is called an instance of that type. Any use
of a value—storing it, passing it as an argument, operating on it—requires a type. This applies in
particular to all variables, arguments, evaluation stack locations, and method results. The type
defines the allowable values and the allowable operations supported by the values of the type.
All operators and functions have expected types for each of the values accessed or used.
Every value has an exact type that fully describes its type properties.
Every value is an instance of its exact type, and can be an instance of other types as well. In
particular, if a value is an instance of a type that inherits from another type, it is also an instance
of that other type.
Value types and reference types
There are two kinds of types: value types and reference types
Value types – The values described by a value type are self-contained (each can be
understood without reference to other values
Reference types –A value described by a reference type denotes the location of another
value. There are four kinds of reference type:
- An object type is a reference type of a self-describing value .Some object types (e.g., abstract classes) are only a partial description of a
value
- An interface type is always a partial description of a value, potentially
supported by many object types.
- A pointer type is a compile-time description of a value whose representation is
a machine address of a location. Pointers are divided into managed and unmanaged
- Built-in reference types.
Boxing and unboxing of values
For every value type, the CTS defines a corresponding reference type called the boxed type. The
reverse is not true: In general, reference types do not have a corresponding value type. The
representation of a value of a boxed type (a boxed value) is a location where a value of the value
type can be stored. A boxed type is an object type and a boxed value is an object.
All value types have an operation called box. Boxing a value of any value type produces its
boxed value; - a value of the corresponding boxed type containing a bitwise copy of the
original value. If the value type is a nullable type—defined as an instantiation of the value type
System.Nullable—the result is a null reference or bitwise copy of its Value property of
type T, depending on its HasValue property (false and true, respectively). All boxed types have
an operation called unbox, which results in a managed pointer to the bit representation of the
value.
(bitwise copy is a copy of a block of memory. by performing a bitwise copy, you're only gonna copy the address of memory it points to.)
Accessibility of members and nested types
- compiler-controlled – accessible only through the use of a definition, not a reference,
hence only accessible from within a single compilation unit and under the control of
the compiler.
- private – accessible only to referents in the implementation of the exact type that
defines the member
- family – accessible to referents that support the same type (i.e., an exact type and all of
the types that inherit from it). For verifiable code , there is an additional
requirement that can require a runtime check: the reference shall be made through an
item whose exact type supports the exact type of the referent. That is, the item whose
member is being accessed shall inherit from the type performing the access
- assembly – accessible only to referents in the same assembly that contains the
implementation of the type
-family-and-assembly – accessible only to referents that qualify for both family and
assembly access
- family-and-assembly – accessible only to referents that qualify for both family and
assembly access
- public – accessible to all referents.
Contracts
Contracts are named. They are the shared assumptions on a set of signatures between all implementers and all users of the contract. The signatures are the part of the contract
that can be checked and enforced. Contracts are not types; rather they specify requirements on the implementation of types. Types
state which contracts they abide by.
- Class contract– A class contract is specified with a class definition. Hence, a class
definition defines both the class contract and the class type.
- Interface contract – An interface contract is specified with an interface definition.
Hence, an interface definition defines both the interface contract and the interface
type
- Method contract – A method contract is specified with a method definition. A method
contract is a named operation that specifies the contract between the
implementation(s) of the method and the callers of the method. A method contract is
always part of a type contract (class, value type, or interface), and describes how a
particular named operation is implemented
-Property contract – A property contract is specified with a property definition. There
is an extensible set of operations for handling a named value, which includes a
standard pair for reading the value and changing the value.
- Event contract – An event contract is specified with an event definition. There is an
extensible set of operations for managing a named event, which includes three
standard methods :
- register interest in an event,
- revoke interest in an event,
- fire the
event
Signatures
Signatures are the part of a contract that can be checked and automatically enforced. Signatures
are formed by adding constraints to types and other signatures. A constraint is a limitation on the
use of or allowed operations on a value or location. Example constraints would be whether a
location can be overwritten with a different value or whether a value can ever be changed.
All locations have signatures, as do all values
There are four fundamental kinds of signatures:
- type signatures
- location signatures
- init-only constraint requires that once the location has been
initialized, its contents never change.
- literal constraint promises that the value of the location is actually a fixed value
of a built-in type
- parameter signatures
- method
signatures
Type safety and verification
Since types specify contracts, it is important to know whether a given implementation lives up to
these contracts. An implementation that lives up to the enforceable part of the contract (the
named signatures) is said to be type-safe. An important part of the contract deals with
restrictions on the visibility and accessibility of named items as well as the mapping of names to
implementations and locations in memory.
Verification is a mechanical process of examining an implementation and asserting that it is
type-safe. Verification is said to succeed if the process proves that an implementation is typesafe. Verification is said to fail if that process does not prove the type safety of an
implementation.
Array types
An array type shall be defined by specifying the element type of the array, the rank (number of
dimensions) of the array, and the upper and lower bounds of each dimension of the array. Hence,
no separate definition of the array type is needed. The bounds (as well as indices into the array)
shall be signed integers. While the actual bounds for each dimension are known only at runtime,
the signature can specify the information that is known at compile time (e.g., no bounds, a lower
bound, or both an upper and a lower bound).