A given assembly may contain any number of distinct types. In the world of .NET, type is simply a general term
used to refer to a member from the set {class, interface, structure, enumeration, delegate}. When you build
solutions using a .NET-aware language, you will most likely interact with many of these types. For example,
your assembly might define a single class that implements some number of interfaces. Perhaps one of the
interface methods takes an enumeration type as an input parameter and returns a structure to the caller.
Recall that the CTS is a formal specification that documents how types must be defined in order to be
hosted by the CLR. Typically, the only individuals who are deeply concerned with the inner workings of the
CTS are those building tools and/or compilers that target the .NET platform. It is important, however, for all
.NET programmers to learn about how to work with the five types defined by the CTS in their language of
choice. The following is a brief overview.
CTS Class Types
Every .NET-aware language supports, at the least, the notion of a class type, which is the cornerstone of
object-oriented programming (OOP). A class may be composed of any number of members (such as
constructors, properties, methods, and events) and data points (fields). In C#, classes are declared using the
class keyword, like so:
CTS Interface Types
Interfaces are nothing more than a named collection of abstract member definitions, which may be
supported (i.e., implemented) by a given class or structure. In C#, interface types are defined using the
interface keyword. By convention, all .NET interfaces begin with a capital letter I, as in the following
example:
On their own, interfaces are of little use. However, when a class or structure implements a given
interface in its unique way, you are able to request access to the supplied functionality using an interface
reference in a polymorphic manner. Interface-based programming will be fully explored in Chapter 8.
CTS Structure Types
The concept of a structure is also formalized under the CTS. If you have a C background, you should be
pleased to know that these user-defined types (UDTs) have survived in the world of .NET (although they
behave a bit differently under the hood). Simply put, a structure can be thought of as a lightweight class type
having value-based semantics. For more details on the subtleties of structures, see Chapter 4. Typically,
structures are best suited for modeling geometric and mathematical data and are created in C# using the
struct keyword, as follows:
CTS Enumeration Types
Enumerations are a handy programming construct that allow you to group name-value pairs. For example,
assume you are creating a video game application that allows the player to select one of three character
categories (Wizard, Fighter, or Thief). Rather than keeping track of simple numerical values to represent
each possibility, you could build a strongly typed enumeration using the enum keyword.
By default, the storage used to hold each item is a 32-bit integer; however, it is possible to alter this
storage slot if need be (e.g., when programming for a low-memory device such as a mobile device). Also,
the CTS demands that enumerated types derive from a common base class, System.Enum. As you will see in
Chapter 4, this base class defines a number of interesting members that allow you to extract, manipulate,
and transform the underlying name-value pairs programmatically.
CTS Delegate Types
Delegates are the .NET equivalent of a type-safe, C-style function pointer. The key difference is that a .NET
delegate is a class that derives from System.MulticastDelegate, rather than a simple pointer to a raw
memory address. In C#, delegates are declared using the delegate keyword.
Delegates are critical when you want to provide a way for one object to forward a call to another object
and provide the foundation for the .NET event architecture. delegates
have intrinsic support for multicasting (i.e., forwarding a request to multiple recipients) and asynchronous
method invocations (i.e., invoking the method on a secondary thread).
CTS Type Members
Now that you have previewed each of the types formalized by the CTS, realize that most types take any
number of members. Formally speaking, a type member is constrained by the set {constructor, finalizer, static
constructor, nested type, operator, method, property, indexer, field, read-only field, constant, event}.
The CTS defines various adornments that may be associated with a given member. For example, each
member has a given visibility trait (e.g., public, private, protected). Some members may be declared as abstract
(to enforce a polymorphic behavior on derived types) as well as virtual (to define a canned, but overridable,
implementation). Also, most members may be configured as static (bound at the class level) or instance (bound
at the object level). The creation of type members is examined over the course of the next several chapters.
Intrinsic CTS Data Types
The final aspect of the CTS to be aware of for the time being is that it establishes a well-defined set of
fundamental data types. Although a given language typically has a unique keyword used to declare a
fundamental data type, all .NET language keywords ultimately resolve to the same CTS type defined in
an assembly named mscorlib.dll. Consider Table , which documents how key CTS data types are
expressed in various .NET languages.
Given that the unique keywords of a managed language are simply shorthand notations for a real type
in the System namespace, you no longer have to worry about overflow/underflow conditions for numerical
data or how strings and Booleans are internally represented across different languages. Consider the
following code snippets, which define 32-bit numerical variables in C# and Visual Basic, using language
keywords as well as the formal CTS data type:
Comments
Post a Comment