All objects are instances of an object type. The object type of an object is set when the object is created and it is immutable. The object type describes the physical structure of the instance and the operations that are allowed on it. All instances of the same object type have the same structure and the same allowable operations. Object types are explicitly declared by a class type definition, with the exception of Array types, which are intrinsically provided by the VES.
Since object type definitions are class type definitions, object type definitions implicitly specify the scope of the name of object type to be the assembly that contains the object type definition, see the Scoping of Names section. Similarly, object type definitions must also explicitly state the visibility attribute of the object type (either public or assembly); see Visibility.
An object type may be marked as abstract by the object type definition. An object type that is not marked abstract is by definition concrete. Only object types can be declared as abstract. Only an abstract object type is allowed to define method contracts for which the type or the VES does not also provide the implementation. Such method contracts are called abstract methods (see Member Definitions). All methods on an abstract class need not be abstract.
It is an error to attempt to create an instance of an abstract object type, whether or not the type has abstract methods. An object type that derives from an abstract object type can be concrete if it provides implementations for any abstract methods in the base object type and is not itself marked as abstract. Instances can be made of such a concrete derived class. Locations may have an abstract type, and instances of a concrete type that derives from the abstract type may be stored in them.
Object type definitions include member definitions for all of the members of the type. Briefly, members of a type include fields into which values are stored, methods that can be invoked, properties that are available, and events that can be raised. Each member of a type can have attributes as described in Type Members.
Object type definitions can declare that they support zero or more interface contracts. Declaring support for an interface contract places a requirement on the implementation of the object type to fully implement that interface contract. Implementing an interface contract always reduces to implementing the required set of methods, i.e. the methods required by the interface type.
The different types that the object type implements, i.e. the object type and any implemented interface types, are each a separate logical grouping of named members. If a class Foo
implements an interface IFoo
and IFoo
declares a member method int a()
and the class also declares a member method int a()
, there are two members, one in the IFoo
interface type and one in the Foo
class type. An implementation of Foo
must provide an implementation for both, potentially shared.
Similarly, if a class implements two interfaces IFoo
and IBar
each of which defines a method int a()
the class must supply two method implementations, one for each interface, although they may share the actual code of the implementation.
CLS Rule 18: CLS-compliant classes, boxed value types, and interfaces must not require the implementation of non-CLS-compliant interfaces.
Object type definitions can declare support for one other class contract. Declaring support for another class contract is synonymous with object type inheritance (see Object Type Inheritance).
New values of an object type are created via constructors. Constructors are defined via a special form of method contract, which defines the method contract as a constructor for a particular object type. The constructors for an object type are part of the object type definition. While the VOS and VES ensure that only a properly defined constructor is used to make new values of an object type, the ultimate correctness of a newly constructed object is dependent on the implementation of the constructor itself.
Object types must define at least one constructor method, but that method need not be public. Creating a new value of an object type by invoking a constructor involves the following steps in order:
Inside the constructor, the object type can do any initialization it chooses (possibly none).
CLS Rule 19: An object constructor must call a base class constructor before any access occurs to inherited instance data.
CLS Rule 20: An object constructor shall not be called except as part of the creation of an object, and no object should be initialized twice.
CLS (consumer): Must provide syntax for choosing the constructor to be called when an object is created.
CLS (extender): Must provide syntax for defining constructor methods with different signatures. May issue a compiler error if the constructor does not obey these rules.
CLS (framework): May assume that object creation includes a call to one of the constructors, and that no object is initialized twice. System.MemberwiseClone and deserialization (including object remoting) may not run constructors.
A class definition that creates an object type can supply an instance method to be called when an instance of the class is no longer accessible. The garbage collector calls finalizers, at most once per instance, automatically.