330 likes | 746 Views
.NET common type system. Role of type system. provides a logically consistent and unchanging foundation ensures that programs can be checked for correctness at runtime type safety (a robust, stable, secure runtime environment) type checking can be specified: informal
E N D
Role of type system • provides a logically consistent and unchanging foundation • ensures that programs can be checked for correctness at runtime type safety (a robust, stable, secure runtime environment) • type checking can be specified: • informal • formal: algorithm-specific language and denotational semantics • put automatic checking into software tools anyone can use them: compilers, linkers, source-code analyzer
in Rotor: ECMA specification contains rules; • when a component is passed to the JIT compiler from the execution engine and is transformed into executable code, during this transformation code is verified according to the rules component are typesafe
Benefits type system: • detecting errors • maintenance • abstraction • documentation • efficiency • security
Reference Types • combination of a location (= identity) and a sequence of bits: • location - designates an area in memory where values can be stored and type; - are type-safe • object types are always reference types, but not all reference types are object types
Object types • object - “anything” that match the criterion: classified as of type System.Object in CLI type system and used according to type’s specification within the CLI execution engine • all object types inherit either directly or indirectly from the Object class. • objects in SSCLI implementation are represented at runtime by the C++ class Object, from file object.h in clr/src/vm directory • all object types descend from this base type, whose definition is:
public class System.Object { public Object( ); public virtual bool Equals (object obj); public static bool Equals (object objA, object objB); //returns true if 2 objects are equal; may be overriden in subtypes public virtual int GetHashCode ( ); // returns the hash code for an object public Type GetType ( ); // returns the type object for this object; allows access to the metadata // for the object public static bool ReferenceEquals (object objA, object objB); public virtual string ToString ( ); // returns a string representatiom of the object . . . }
Others: • MemberwiseClone – returns a shallow copy of the object; • Finalize – invoked by the garbage collector before an object’s memory is reclaimed; • Most of the methods are public; • Some (MemberwiseClone, Finalize) have protec-ted access.
Components • = abstract units of interoperability and reuse for programmers working with languages that target CLI • defined using types & manipulated using high-level languages • autonomous, replaceable units, adaptive over time • modified and deployed without changing other components • in Rotor: • object – instance of type System.Object • component – more general role (used when others say “object”)
Interface types • = a partial specification of a type; • partition types into categories of related functionality • A contract that binds implementers to provide implementations of the methods contained in the interface. • Object types may support several interface types, and several different object types would normally support an interface type • By definition, an interface types can never be an object type or an exact type. • Interface types may extend other interface types.
May contain: • Methods (both class and instance) • Properties • Events. • Cannot contain instance fields (major difference from object or value type) • respects interface purposes from other languages (C++, Java): • method declaration on an interface (state represented as accessor and mutator – set & get) • behavior is represented as nonstate-related methods • notification involves a callback interface that client components must implement
Example: #using <mscorlib.dll> using namespace System; _gc _interface Ipoint { _property int get_X ( ); _property void set_X (int value); _property int get_Y ( ); _property void set_Y (int value); }; _gc class Point: public Ipoint { . . . };
CLR provides a number of interface types • Example: IEnumerator interface supported by array objects • Allows clients of arrays to enumerate over the array by requesting an IEnumerator interface; supports 3 methods: • Current – returns the current object • MoveNext – moves the enumerator on to the next object • Reset – reset the enumerator to its initial position.
Pointer Types • Provide a means of specifying the location of code or value • 3 categories: • Function pointers refer to code • Managed pointers can point at objects located on the garbage-collected heap; A managed pointer & is similar to the object type, but points to the interior of an object. Managed pointers are not interchangeable with object references.
Unmanaged pointers* can address local variables and parameters • are the traditional pointers of other runtime systems, that is, the addresses of data; • are an essential element for the interoperation of CLI programs with native code components. Such pointers may not point into the managed heap since such heap values are under the control of a garbage collector that is free to move and compact objects. • Conversely, values of managed pointer type may safely point outside the managed heap, since the garbage collector knows the heap limits.
Built-in Types • There are built-in value and reference types • Have special instructions in the intermediate langauge, so that they can be handled efficiently by the execution engine • Built-in types are: • Bool • Char (16-bit Unicode) • Integers (signed + unsigned; 8-, 16-, 32-, 64-bit) • Floating point numbers (32- and 64-bit) • Object // inbuilt reference type • String // inbuilt reference type • Machine-dependent integers (signed + unsigned) // hold the largest value that an array index can support on a machine • Machine-dependent floating point
Metadata • the essential link that bridges the runtime type system and the execution engine; • 2 problems: • information about the component (its metadata) is often not stored with the component; often stored in auxiliary files (IDL files, type libraries, interface repositories, implementation repositories, Registry) CLR stores metadata with types • metadata facilities are primitive: allow developer to specify syntax but not semantics of interfaces CLR provides a standardized metadata extension system known as custom attributes
Compilers targeting .NET describe types with metadata for 2 reasons: • metadata allow types defined in one language to be used in another langauge - ensures langauge interoperability in CLR • the execution engine requires metadata to manage objects. • Metadata are stored in files in a binary format; the format is not specified, but there are methods for reading and writing metadata. • Metadata are extensible through custom attributes.
Using types in data-driven code • to use type information to drive program decisions is called introspection or reflection – component’s code is reflec-ting on its own structure and making decisions based on this information • programs (when having permission) can create, manipulate and examine type metadata from: • managed code – using System.Reflection family of types • unmanaged code – using unmanaged APIs described in clr/src/inc/metada.h • type descriptions are used to defer decisions until runtime, enabling unbound linkages between components
What we want: ability to place information at the type level into the code, available to interested parties, but otherwise a non-intrusive specification • Case study: to take an existing in-memory object instance and save its current state to some secondary storage stream (e.g. the filesystem, sent as part of an HTTP request a.s.o.) • object-oriented approach: • common behavior across types, should be represented as a base type from which derived types inherit their functionality
C++ style (multiple inheritance) • one problem: base type knows nothing of the derived type’s data, although need to store its data • second problem: with multiple inheritance, require the argument for multiple inheritance within the system
Java style (single inheritance +interface) • one solution: create an interface that serves as a well-understood “flag” to components to indicate that this type wants to participate in the “object-to-disk” behavior. • a type inherits this “marker interface”, which has no methods, and when instances of this type are passed to the “object-to-disk” APIs, the flag is checked to ensure that this type does want to be stored.
BUT: • the level of granularity on the interface is centered on methods; • if the component wants additional information about storing on the disk, needs a method in the interface, called by the storing APIs, to obtain that information • components to be stored must implement those methods => API of the component will contain code that isn’t domain related
CLI approach • solution: custom attributes • attributes are metadata attached to various facets of types, using either special language syntax or tools that enable after-the-fact type annotation • because metadata for any object instance is available through the reflection APIs, the code to implement the writing out of values is easy
Example using System; // gradfather in C#namespace Smith { public class Grandfather { public Grandfather() { Name = "Smith"; FirstName = "GrandDad"; } public string Name; public string FirstName; public virtual int Age() { return(85); } };};
Imports System; //father in VB Namespace Smith Public Class Father Inherits Grandfather Public Sub New( ) FirstName = "Father" End Sub Public Overrides Function Age() As Integer Age = 45 End Function End Class End Namespace
#using <mscorlib.dll> //son in managed C++ using namespace System; #using "Father.dll“ namespace Smith { __gc public class Son : public Father { public: Son() { FirstName = S"Son"; } int Age() { return(5); } };};