Some languages ??can require types that other languages ??do not support. To allow for this, there are additional CLR types that support the functionality required for specific languages ??such as C #. However, one caveat with sharing CLR classes created with different languages ??means that there is the potential that a class will not be usable in certain languages ??if its types are not understood. For example, the C # language has types such as the unsigned long that are not available in languages ??such as VB, so a C # class that uses an unsigned long as part of its public member definitions cannot be used in VB. However, the same class can be used if such types are used in non-public member definitions. A common set of base types exists to help ensure types created by different languages ??are compatible. This is part of the CLS. Most CLR compilers have options to flag warnings if non-CLS types are used. Everything in the CLR Is an Object
Every type in the CLR is an object. As seen in the previous table, all types are derived from System.Object. When you define your own custom types such as classes, structures, and enumerations, they are automatically derived from System.Object, even though the inheritance isn explicitly defined. When a class is compiled, the compiler will automatically do this. As every type has a common base type (System.Object), you can write some very powerful generic code. For example, the System.Collections namespace provides lots of collection classes that work with System. Object (for instance, the Hashtable class is a simple dictionary class populated using a name and a System.Object reference). By using either a name or an index, you can retrieve an object reference from the collection very efficiently. Since all types derive from System.Object, you can hold any type in a Hashtable. If you e a C / C developer or an experienced VB programmer, you e probably thinking that having every type in the CLR as an object is expensive, since primitive types such as Integer, Long, and Structure in VB6 and C / C only require space to be allocated on the stack, whereas object references require allocated space on the heap. To avoid having all types heap allocated, which would compromise code execution performance, the CLR has the following two types: Value types : They are allocated on the stack, just like primitive types in VBScript, VB6, and C / C . Reference types : They are allocated on the managed CLR heap, just like object types. It is important to understand how the CLR manages and converts these types using boxing and unboxing, to avoid writing inefficient code. Value types are not instantiated using New (unless you have a parameterized constructor ), and go out of scope when the function they are defined within returns. Value types in the CLR are defined as types that derive from System.ValueType. All of the CLR primitive types such as System.Int32 derive from this class, and when structures are defined using Visual Basic. NET and C # those types automatically derive from System.ValueType. Here is an example Visual Basic. NET structure that represents a CLR value type called Person: The equivalent C # structure is: Both compilers will emit IL that defines a Person type that inherits from System.ValueType. The CLR will therefore know to allocate instances of this type on the stack. When using CLR classes such as the Hashtable that work with collections of System.Object types, you need to be aware that the CLR will automatically convert value types into reference types. This conversion happens when you assign a value type, such as a primitive type like System.Int32, to an Object reference, or vice versa. The following code will implicitly box an Integer value when it is assigned to an Object reference: When boxing occurs, the contents of a value type are copied from the stack into memory allocated on the managed heap. The new reference type created contains a copy of the value type, and can be used by other types that expect an Object reference. The value contained in the value type and the created reference types are not associated in any way (except that they contain the same values). If you change the original value type, the reference type is not affected. The following code explicitly unboxes a reference type into a value type: When unboxing occurs, memory is copied from the managed heap to the stack. Understanding boxing and unboxing is important, since it has performance implications. Every time a value type is boxed, a new reference type is created and the value type is copied onto the managed heap. Depending on the size of the value type, and the number of times value types are boxed and unboxed, the CLR can spend a lot of CPU cycles just doing these conversions. To put all this type theory into practice, take a look at the following Visual Basic. NET code, which illustrates when value types and reference types are used, and when boxing and unboxing occurs: Let start by declaring a simple structure called Person that can hold a name and an age. Since structures are always value types (remember compilers automatically derive structures from System.ValueType), instances of this type will always be held on the stack: Then begin your main module: First, create a Hashtable. This is a reference type, so use New to create an instance of the object, which will be allocated on the managed CLR heap: Hashtable and other collections classes are explained in more detail in Chapter 15. Next, initialize your Person structure with some values. This is a value type, so you don have to use New, since the type is allocated automatically on the stack when you declare your variable: Once your Person structure is initialized, add it to the dictionary using a key of Rich. This method call will implicitly cause the value type to be boxed within a reference type, as we discussed, since the second parameter of the Add method expects an Object reference: Next, change the values ??of the same Person structure variable to hold some new values: Then add another person to the dictionary with a different key. Again, this will cause the value type to be boxed within a reference type and added to the dictionary: At this point, you have a Hashtable object that contains two reference types. Each of these reference types contains your Person structure value type, with the values ??we initialized. You can retrieve an item from the Hashtable using a key. Since the Hashtable returns object references, you can use the CType keyword to tell Visual Basic. NET that the object type returned by the Itemfunction is actually a Person type. Since the Person type is a value type, the CLR knows to unbox the Person type from the returned reference type: And now you can use the Person type:
The CLR provides access to common base functionality (such as string searching) for all languages ??via the Base Class Library (BCL). The CLR is basically a replacement for the WIN32 API and COM. It provides the foundation on which the. NET vision has been realized, since most of the Windows DNA limitations stem from features of these technologies. More importantly for VB developers, the WIN32 API provided a lot of functionality they could not easily use previously, such as process creation and free-threaded support. Since that functionality is now part of the CLR, VB (and other languages ??such as COBOL) can now create high-performance multi-threaded applications. The CLR is object-oriented. All of the functionality of the CLR and the class libraries built on top of it are exposed as methods of objects. These classes are as easy to use as the ASP intrinsic objects and ADO objects you used previously, but are far richer in functionality. Using Objects
csc / t: library / r: base.dll derived. cs
The CLR provides many core services for applications, such as garbage collection, code verification, and code access security. The CLR can provide these services due to the way it manages code execution, and the fact that – thanks to the rich metadata compilers produce – it can understand all types used within code. Garbage collection is a CLR feature that automatically manages memory on behalf of an application. You create and use objects, but do not explicitly release them. The CLR automatically releases objects when they are no longer referenced and in use. This eliminates memory leaks in applications. This memory management feature is similar in some ways to how VB works today, but, under the hood, the implementation is radically different and much more efficient. A key difference is that the time at which unused memory will be released is non-deterministic. One side effect of this feature is that you cannot assume an object is destroyed when it goes out of the scope of a function. Therefore you should not put code into a class destructor to release resources. You should always release them in the code using a method, as soon as possible. Code verification is a process that ensures all code is safe to run prior to execution. Code verification enforces type safety, and therefore prevents code from performing illegal operations such as accessing invalid memory locations. With this feature it should not be possible to write code that causes an application to crash. If code does something wrong, the CLR will throw an exception before any damage is inflicted. Such exceptions can be caught and handled by an application. Code access security allows code to be granted or denied permissions to do things, depending on the security configuration for a given machine, the origins of the code, and the metadata associated with types that the code is trying to use. The primary purpose of this feature is to protect users from malicious code that attempts to access other code residing on a machine. For example, with the CLR, you could protect your applications and users when writing an e-mail application by denying all rights to code contained within an e-mail so that it cannot use other classes such as the address book or file system. The code produced for an application designed to run under the CLR is called managed code – self-describing code that makes use of and requires the CLR to be present. Code written with languages ??like VB6 that doesn provide IL and doesn need the CLR to run is called unmanaged code. For managed code, the CLR will: Always locate the metadata associated with a method at any point in time. Walk the stack. Handle exceptions. Store and retrieve security information. These low-level requirements are necessary for the CLR to watch over code, provide the services we e discussed, and ensure its integrity for security and protection reasons. Common Functionality
The CLR is one of the most radical features of. NET. Modern programming languages ??like VC and VB have always had runtimes. These are sometimes very small, like MSCRT40.DLL (used by Visual C applications) , and other times, they can be quite big, like MSVBVM60.DLL (used by Visual Basic 6). A language runtime role changes depending on the language; it may actually execute the code (as in the case of Java, or VB applications compiled using p-code), or in the case of native compiled languages ??(like C / C ), may provide common functionality used by the application. Some of this runtime functionality may be used directly by an application (such as searching for a character sequence in a string), or indirectly by a compiler that injects additional code during the compilation process to handle error situations or exceptions (such as a user aborting an application). The CLR is a runtime for all. NET languages. It is responsible for executing and managing all code written in any language that targets the. NET platform. The role of the CLR in some ways is similar to Sun Java Virtual Machine (JVM) and the VB runtime. It is responsible for the execution of code developed using. NET languages. However, the critical point that differentiates the CLR is that it natively compiles all code. Although. NET compilers emit Intermediate Language (IL) code rather than pure machine code, the IL is JIT-compiled before code is executed. IL is not interpreted, and it is not byte code like the p-code used by VB or the code used by Java. IL is a language. It is compiled, converted into machine code, and then executed. The result is that applications targeting. NET , and which execute on the CLR, have exceptionally good application performance. To complement IL, compilers that target the CLR also emit rich metadata that describes the types contained with a DLL or EXE (similar to COM type libraries but much richer) and version / dependency information. This metadata allows the CLR to intelligently resolve references between different application files at runtime, and also removes the dependency on the system registry. As we discussed earlier, these are two common problem areas for Windows DNA applications. CLR Services
To see how to create and use objects with the CLR, let walk through some simple examples. In these, you will see how to create: (no time for the the detail … …)
using Wrox.Books.ProASPNet ; public class MyCSharpClass: MyVBClass {}
This namespace import declaration makes the types within the Wrox.Books.ProASPNet namespace available to any of the code in your C # file. Namespaces have two key functions: They logically group related types : For example, System.Web contains all ASP.NET classes that manage the low-level execution of a Web request. System.Web.UI contains all of the classes that actually render UI, and System.Web . Hosting contains the classes that aid in ASP.NET being hosted inside IIS or other applications. They make name collision less likely : In an object-oriented world, many people are likely to use the same class names . The namespace reduces the likelihood of a conflict, since the fully qualified name of a class is equal to the namespace name plus the class name. You can choose to use fully qualified names in your code, and forgo the namespace import declaration. However, you l typically only do this if you have a namespace that contains the classes that ASP.NET uses for hosting inside IIS or the other applications. Namespaces are used extensively in the CLR, and since ASP.NET pages are compiled down to CLR classes , they will be used extensively in your ASP.NET pages. For this reason, ASP.NET automatically imports the most common names into an ASP.NET page. As you l see later in the book, this list can be extended to include your own classes. It helps to think of namespaces as directories. Rather than containing files, they contain classes. However, a namespace called Wrox.MyBook does not mean a namespace called Wrox exists. It is likely that it does, but it is not mandatory. For the CLR to make cross-language integration so smooth, all languages ??have to use a common type system. The following table lists the types that form part of the CLS, and defines the types usable in any language targeting the CLR: System . Boolean Represents a Booleanvalue. True or False. The CLS does not allow implicit conversion between Boolean and other primitive types. System.Byte Represents an unsigned byte value. Positive integer between 0 and 255. System.Char Represents a UNICODE character value. Any valid UNICODE character. System.DateTime Represents a date and time value. IEEE 64-bit (8-byte) long integers that represent dates ranging from 1 January 1 CE (the year 1) to 31 December 9999 and times from 0:00: 00 to 23:59:59. System.Decimal Represents positive and negative values ??with 28 significant digits. 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. System.Double Represents a 64-bit, double precision, floating point number. Negative 1.79769313486231570E 308 to positive 1.79769313486231570 E 308. System.Int16 Represents a 16-bit signed integer value. Negative 32768 to positive 32767. System.Int32 Represents a 32-bit signed integer value. Negative 2,147,483,648 to positive 2,147,483,647. System.Int64 Represents a 64-bit signed integer . Negative 9,223,372,036,854,775,808 to positive 9,223,372,036,854,775,807. System.Sbyte Represents an 8-bit signed integer. Negative 128 to positive 127. System.Single Represents a 4-byte, single precision, floating point number. Negative 3.402823E38 to positive 3.402823E38. System. TimeSpan Represents a period of time, either positive or negative. The MinValue field is negative 10675199.02:48:05.4775808. The MaxValue field is positive 10675199.02:48:05.4775807. System.String Represents a UNICODE String. Zero or more UNICODE characters. System. Array Represents a single dimension array. Range is based upon declaration and usage. Arrays can contain other arrays. System.Object The base type from which all other types inherit. NA Different languages ??use different keywords to expose these types. For example, VB will convert variables you declare as type Integer to System.Int32 during compile time, and C # will convert intinto System.Int32. This makes working with different languages ??more natural and intuitive, while not compromising any goals of the CLR. You can of course declare the native CLR type names in any language, but you typically wouldn do this unless the language did not have its own native mapping. This is another great feature of the CLR. If the language doesn support a feature, you can usually find some. NET Framework classes that do. All types derive from System.Object. This class has four methods (all of these methods are available on all types) as shown in the following table: Equals Allows two object instances to be compared for equality. Most CLR classes override this and provide a custom implementation. For example, System.ValueType has an implementation that compares all members fields for equality. Value types are discussed shortly. GetHashCode Returns a hash code for the object. This function is used by classes such as Hashtable to get a unique identity for an object. Two objects of the same type that represent the same value will always return the same hash code. GetType Returns a Type object that can be programmatically used to explore the methods, properties, and events of a type. This feature of the CLR is called reflection. ToString Returns a string representation of the type. The default implementation returns the fully qualified type name suitable in aiding debugging. Most CLR types override this method and provide a more useful return value. For example, System.Int32 will return a string representation of a number. Common Language Specification
Namespace Wrox.Books.ProASPNet Public Class MyVBClass End ClassEnd Namespace
2010 年 12 月 16 日
vbc base . vb / t: library