dot.NET.Framework.Essentials.1002003,.3Ed [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

dot.NET.Framework.Essentials.1002003,.3Ed [Electronic resources] - نسخه متنی

Hoang Lam; Thuan L. Thai

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










2.6 The CTS and CLS


Having seen the importance of metadata and IL, let's
examine the CTS and the CLS. Both the CTS and the CLS ensure language
compatibility, interoperability, and integration.


2.6.1 The Common Type System (CTS)


Because .NET treats all languages as equal, a
class written in C# should be equivalent to a class written in
VB.NET, and an interface defined in Managed C++ should be exactly the
same as one that is specified in Managed COBOL. Languages must agree
on the meanings of these concepts before they can integrate with one
another. In order to make language integration a reality, Microsoft
has specified a common type system by which every .NET language must
abide. In this section, we outline the common types that have the
same conceptual semantics in every .NET language. Microsoft .NET
supports a rich set of types, but we limit our discussion to the
important ones, including value types, reference types, classes,
interfaces, and delegates.

2.6.1.1 Value types


In general, the CLR supports two different types: value types and
reference types. Value
types
represent values allocated on the stack. They cannot be null and must
always contain some data. When value types are passed into a
function, they are passed by value, meaning that a copy of the value
is made prior to function execution. This implies that the original
value won't change, no matter what happens to the
copy during the function call. Since intrinsic types are small in
size and don't consume much memory, the resource
cost of making a copy is negligible and outweighs the performance
drawbacks of object management and garbage collection. Value types
include primitives, structures, and enumerations; examples are shown
in the following C# code listing:

int i; // Primitive
struct Point { int x, y; } // Structure
enum State { Off, On } // Enumeration

You can also create a value type by deriving a class from
System.ValueType. One thing to note is that a
value type is sealed, meaning that once you have
derived a class from System.ValueType, no one else
can derive from your class.

2.6.1.2 Reference types


If a type
consumes significant memory resources, then a reference type provides
more benefits over a value type. Reference types
are so called because they contain references to heap-based objects
and can be null. These types are passed by reference, meaning that
when you pass such an object into a function, an address of or
pointer to the object is passednot a copy of the object, as in
the case of a value type. Since you are passing a reference, the
caller will see whatever the called function does to your object. The
first benefit here is that a reference type can be used as an output
parameter, but the second benefit is that you don't
waste extra resources because a copy is not made. If your object is
large (consuming lots of memory), than reference types are a better
choice. In .NET, one drawback of a reference type is that it must be
allocated on the managed heap, which means it requires more CPU
cycles because it must be managed and garbage-collected by the CLR.
In .NET, the closest concept to destruction is finalization, but
unlike destructors in C++, finalization is nondeterministic. In other
words, you don't know when finalization will happen
because it occurs when the garbage collector executes (by default,
when the system runs out of memory). Since finalization is
nondeterministic, another drawback of reference types is that if
reference-type objects hold on to expensive resources that will be
released during finalization, system performance will degrade because
the resources won't be released until these objects
are garbage-collected. Reference types include classes, interfaces,
arrays, and delegates, examples of which are shown in the following
C# code listing:

class Car {} // Class
interface ISteering {} // Interface
int[] a = new int[5]; // Array
delegate void Process( ); // Delegate

Classes, interfaces, and delegates will be discussed shortly.

2.6.1.3 Boxing and unboxing


Microsoft .NET supports value types for
performance reasons, but everything in .NET is ultimately an object.
In fact, all primitive types have corresponding classes in the .NET
Framework. For example, int is, in fact, an alias
of System.Int32, and System.Int32 happens to derive from
System.ValueType, meaning that it is a value type. Value types are
allocated on the stack by default, but they can always be converted
into a heap-based, reference-type object; this is called
boxing. The following code snippet shows that we
can create a box and copy the value of i into it:

int i = 1; // i - a value type
object box = i; // box - a reference object

When you box a value, you get an object upon which you can invoke
methods, properties, and events. For example, once you have converted
the integer into an object, as shown in this code snippet, you can
call methods that are defined in System.Object,
including ToString( ), Equals(
)
, and so forth.

The reverse of boxing is of course unboxing, which
means that you can convert a heap-based, reference-type object into
its value-type equivalent, as the following shows:

int j = (int)box;

This example simply uses the cast operator to cast
a heap-based object called box into a value-type
integer.

2.6.1.4 Classes, properties, indexers


The CLR
provides full support for object-oriented concepts
(such as encapsulation, inheritance, and polymorphism) and class
features (such as methods, fields, static members, visibility,
accessibility, nested types, and so forth). In addition, the CLR
supports new features that are nonexistent in many traditional
object-oriented programming languages, including properties,
indexers, and events.Chapter 8. For now
let's briefly talk about properties and indexers.

[10] An event is a callback that is
implemented using delegates, which is covered shortly.


A property is similar to a field (a member variable), with the
exception that there is a getter and a setter method, as follows:

using System;
public class Car
{
private string make;
public string Make
{
get { return make; }
set { make = value; }
}
public static void Main( )
{
Car c = new Car( );
c.Make = "Acura"; // Use setter.
String s = c.Make; // Use getter.
Console.WriteLine(s);
}
}

Although this is probably the first time you've seen
such syntax, this example is straightforward and really needs no
explanation, with the exception of the keyword
value. This is a
special keyword that represents the one and only argument to the
setter method.

Syntactically similar to a property, an indexer is analogous to
operator[] in C++, as it allows array-like access
to the contents of an object. In other words, it allows you to access
an object like you're accessing an array, as shown
in the following example:

using System;
public class Car
{
Car( )
{
wheels = new string[4];
}
private string[] wheels;
public string this[int index]
{
get { return wheels[index]; }
set { wheels[index] = value; }
}
public static void Main( )
{
Car c = new Car( );
c[0] = "LeftWheel"; // c[0] can be an l-value or an r-value.
Console.WriteLine(c[0]);
}
}


Unlike C++, but similar to Java, classes in .NET support only
single-implementation inheritance.

2.6.1.5 Interfaces


Interfaces support
exactly the same concept as a C++
abstract base class (ABC) with only
pure virtual functions. An ABC is a class that declares one or more
pure virtual functions and thus cannot be instantiated. If you know
COM or Java, interfaces in .NET are conceptually equivalent to a COM
or Java interface. You specify them, but you don't
implement them. A class that derives from your interface must
implement your interface. An interface may contain methods,
properties, indexers, and events. In .NET, a class can derive from
multiple interfaces.

2.6.1.6 Delegates


One of the most
powerful features of C is its support for function pointers. Function
pointers allow you to build software with hooks that can be
implemented by someone else. In fact, function pointers allow many
people to build expandable or customizable software. Microsoft .NET
supports a type-safe version of function pointers, called
delegates. Here's an example
that may take a few minutes to sink in, but once you get it,
you'll realize that it's really
simple:

using System;
class TestDelegate
{
// 1. Define callback prototype.
delegate void MsgHandler(string strMsg);
// 2. Define callback method.
void OnMsg(string strMsg)
{
Console.WriteLine(strMsg);
}
public static void Main( )
{
TestDelegate t = new TestDelegate( );
// 3. Wire up our callback method.
MsgHandler f = new MsgHandler(t.OnMsg);
// 4. Invoke the callback method indirectly.
f("Hello, Delegate.");
}
}

The first thing to do is to define a callback function prototype, and
the important keyword here is delegate, which
tells the compiler that you want an object-oriented function pointer.
Under the hood, the compiler generates a nested class, MsgHandler,
which derives from System.MulticastDelegate.[11] A multicast
delegate supports many receivers. Once you've
defined your prototype, you must define and implement a method with a
signature that matches your prototype. Then, simply wire up the
callback method by passing the function to the
delegate's constructor, as shown in this code
listing. Finally, invoke your callback indirectly. Having gone over
delegates, you should note that delegates form the foundation of
events, which are discussed in Chapter 8.

[11] If you
want to see this, use ildasm.exe and view the
metadata of the delegate.exe sample that
we've provided.



2.6.2 The Common Language Specification (CLS)


A goal of .NET is to support
language integration in such a way that programs can be written in
any language, yet can interoperate with one another, taking full
advantage of inheritance, polymorphism, exceptions, and other
features. However, languages are not made equal because one language
may support a feature that is totally different from another
language. For example, Managed C++ is case-sensitive, but VB.NET is
not. In order to bring everyone to the same sheet of music, Microsoft
has published the Common Language Specification (CLS). The CLS
specifies a series of basic rules that are required for language
integration. Since Microsoft provides the CLS that spells out the
minimum requirements for being a .NET language, compiler vendors can
build their compilers to the specification and provide languages that
target .NET. Besides compiler writers, application developers should
read the CLS and use its rules to guarantee language interoperation.


/ 121