1. Trang chủ
  2. » Công Nghệ Thông Tin

Accelerated VB 2005 phần 2 doc

43 178 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Shared assemblies and assembly loading in VB 2005
Trường học University of Technology Ho Chi Minh City
Chuyên ngành Computer Science
Thể loại Lecture Notes
Năm xuất bản 2007
Thành phố Ho Chi Minh City
Định dạng
Số trang 43
Dung lượng 551,81 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Once you have a type object, you can find out if it’s a class, an interface, a structure, and so on, what methods it has, and the number and types of fields it contains.. The most common

Trang 1

Figure 2-2.Shared assemblies are located in the GAC.

If the Culture entry is blank for an assembly, it means that it’s culture-neutral, which iscommon for assemblies that contain only code If you develop applications that require local-ization, it’s recommended that you isolate all of your resources in a separate assembly so thatthey can be swapped out easily with a different culture without affecting your code Sharedassemblies bring us to the concept of assembly naming Assemblies can be named in twoways:

• Strongly (or fully) named: An assembly that has a four-part name consisting of the short

assembly name, a version number, a culture identifier in ISO format, and a hash token

If an assembly is named with all four parts, it’s considered to be strongly named

• Partially named: An assembly that contains only the short assembly name and a

ver-sion number

Shared assemblies must be strongly named, and only strongly named assemblies can beregistered in the GAC The strong names are required so that the consuming application canidentify the assembly and thus verify that it’s safe to use Registering an assembly in the GAC isanalogous to registering a COM server in the registry If the assembly is not strongly named, itmay only be used locally by the application To deploy a shared assembly, use the command-line utility gacutil.exe This utility is used to view, install, and uninstall assemblies in theGAC Table 2-1 describes some of the available command-line switches that you can use withgacutil.exe:

Trang 2

Table 2-1.gacutil.exe Command-Line Switches

/u Remove the assembly from the GAC, if no other references to it exist

/il Use a text file containing assembly names to be installed

/ul Use a text file containing assembly names to be removed

/l Display a listing of installed assemblies

Note Using partially named assemblies with the /uor /ulswitches may remove multiple assemblies

Loading Assemblies

The assembly loader goes through a very detailed process, called probing, to load an assembly.

The loader attempts to locate and load an assembly based on the exact version number in the

manifest However, you can direct the loader to load a different version of an assembly by

specifying it in a config file such as the application config file, the machine config file, or a

publisher policy file (a file that directs an application to use a newer version of an assembly)

The loader looks for partially named assemblies in the same directory as the running

applica-tion or in a subdirectory If an assembly is strongly named, then the loader will first search the

GAC before probing local directories

The assembly loader follows a certain process to locate the correct assembly during ing This series of steps is quite detailed, and you can find more about how the runtime loads

prob-assemblies on Microsoft’s developer website (see Resources), but here’s the process in a

nut-shell:

1. The runtime first checks any config files for the correct version of the assembly that it’sloading

2. If the assembly has already been loaded, the runtime will use the loaded assembly

3. The loader checks the GAC, and if it finds the assembly, it loads it

4. The runtime then follows certain probing rules, first looking in the location specified

by a <codebase> element in a config file or publisher policy The loader attempts tolocate the file based on the location, the assembly name, culture information, and version

5. If the loader can’t locate the assembly after probing for it, an error is thrown

When architecting your application, keep in mind that there’s overhead when locatingand loading assemblies This is something to consider when it comes to deciding on the num-

ber of assemblies you want to create As you can see, versioning plays a key role at assembly

load time, and all assemblies are versioned Versioning is something that was built into the

Trang 3

CLR loader from the beginning and removes the affliction, affectionately known as DLL Hell,

that occurs when replacing a shared DLL with a newer version breaks applications that usethe older version In the CLR, multiple versions of the same assembly can exist simultaneously

on the same machine without conflicting with each other Moreover, applications can choose

to default to using the most recent version of an assembly on the machine, or you can specifythe exact version they prefer by applying a version policy in their configuration files

Cross-Language Compatibility

Because assemblies are self-describing and contain portable IL code, they are easily sharedacross multiple languages Finally, there’s a viable solution for creating complex systems inwhich components are coded using different languages For example, in a complex systemused for engineering analysis, you may have a group of VB developers coding the system infrastructure and a group of engineers developing the mathematical components Manyengineers still program in languages such as FORTRAN, and this works because there areFORTRAN compilers available that emit IL and create managed assemblies Thus, each development group can work in a language that’s more natural to them and to their problemdomains Metadata is the key to cross-language compatibility The metadata format is com-pletely described in the CLI Ecma standards documents

Metadata: Better Than COM

It’s easy to gloss over the importance of metadata and the advantages it offers As you’ve seen,all managed modules are self-describing through the use of metadata Metadata is not a newconcept, but its implementation in NET, in concert with the CTS, is a huge improvement overCOM, solving many of its shortcomings

Language interoperability issues that existed in COM have been resolved because nowany NET language must conform to the CLI standard and support all the necessary types

In COM, a component written in one language didn’t guarantee it could by used by anotherlanguage For example, a C++ component may not have been usable by a VB program because

it could contain types unsupported by VB

Assembly metadata also alleviates inconsistencies that were experienced in COM Ifyou’ve created COM components, you may know that there were two options for metadata:Interface Description Language (IDL) and type libraries (TLBs) IDL is a platform-independ-ent description language for interfaces and components Typically, you provide your

consumer with the COM component packaged in either a DLL or an EXE along with the IDL.The consumer typically takes the IDL and passes it through an IDL compiler to produce nativecode that the consumer can then interface with

A TLB serves much the same purpose as IDL, but it’s in binary format that high-level guages such as VB typically consume Unfortunately, IDL and TLBs don’t overlap entirely, andsome things can be described in IDL but not in TLBs and vice versa All assemblies created in.NET follow the same metadata format, so you never have to worry about consumers access-ing your objects Additionally, assembly structure and manifests mean no more issues related

lan-to registry entries and versioning that were prevalent with COM applications

Metadata is an extensible format for describing the contents of assemblies If it’s notexpressive enough for your needs, you can define new, custom “attributes” that are easily

Trang 4

included in the metadata for a type In the managed world, just about every entity in a

pro-gram with a type can have metadata attached to it, including classes, interfaces, methods,

parameters, return values, assemblies, and so on You define custom attributes by deriving

from the System.Attribute class Then you can easily associate an instance of your custom

attribute to just about any entity in your assembly

To top it all off, you can access metadata at run time For example, at run time, you caniterate over all the fields of an arbitrary class type without having to know its declaration

ahead of time or at compile time This power opens up the possibility of entire programs and

types being generated dynamically at run time

Reflection

With metadata, you can programmatically access and examine type definitions and the

attrib-utes attached to them Metadata can tell you if a particular object’s class supports a given

method before attempting to call it or if a given class is derived from another The process of

inspecting metadata is called reflection Classes in the System.Reflection namespace are used

to retrieve type information at run time Typically, you start with a System.Type object when

you reflect upon types in the assembly Once you have a type object, you can find out if it’s a

class, an interface, a structure, and so on, what methods it has, and the number and types of

fields it contains

Summary

In this chapter, we covered the essentials of how a VB program is compiled, packaged, and

executed We looked at how your VB code gets compiled into IL and is then compiled on the

fly by the JIT compiler One of the requirements for JIT compilation is an expressive and

extensible mechanism that the compiler can understand—thus, we have assemblies By

pack-aging IL into assemblies that are self-documenting, both the CLR and the JIT compiler have all

the information they need to manage code execution Private assemblies make it possible to

run multiple versions of code without having to worry about registry entries or overwriting

COM components Shared assemblies provide the ability to access the functionality of a single

assembly from multiple applications Now that you have an idea of how VB programs run,

we’ll jump into some VB syntax in the next chapter

Trang 6

VB Syntax

This chapter is an introduction to the syntax of the Visual Basic (VB) language The topics

covered here are the glue that binds programs together We’ll take a close look at types and

variables, since the common type system (CTS) is a key component of the NET common

language runtime (CLR) By the same token, the type system is one facet of VB that is very

different in NET from previous versions We’ll also look at namespaces; this is a NET concept

you’ll put into practice as soon as you write your first program Understanding namespaces

not only helps you navigate the VB namespaces to find the classes you need, but it also helps

you to create your own namespaces in a logical manner We’ll wrap up with an overview of VB

control flow statements, which differ in syntax but are the same in concept across all

lan-guages

In this chapter, we assume you have some experience with a previous version of VB

Although it’s obvious that the VB language was designed to leverage the knowledge of VB

developers, you’ll notice that it’s quite a departure from Visual Basic 6 (VB6) If you’re coming

from a VB6 development background, some of the new language features may be new to you,

but it won’t be long before you feel right at home with VB syntax

Types and Variables

Types in VB can be either value types or reference types Value types, such as structures and

built-in types, are allocated on the stack and contain their associated data Reference types,

such as classes and arrays, are allocated on the managed heap, while a reference (pointer) to

the object is stored on the stack As we progress through this chapter, we’ll discuss types and

variables in more detail Chapters 4 and 5 will continue the discussion in greater depth

Strong Typing

VB is a strongly typed language Well, to be more precise, VB can be a strongly typed language.

Strong typing means that every variable and object instance that’s declared must be of a

well-defined type A strongly typed language provides rules for how variables of different types can

25

C H A P T E R 3

Trang 7

interact with each other Strongly typed variables enable the compiler to check that the tions being performed on variables and objects are valid For example, suppose you have amethod that computes the average of two integers and returns the result The method isdeclared in VB as follows:

opera-Function ComputeAvg(ByVal Param1 As Integer, ByVal Param2 As Integer) As DoubleComputeAvg = (Param1 + Param2) / 2

End Function

This method accepts two integers and returns a double Therefore, if you attempt to callthis method and pass in two Customer objects, you’ll receive a compile-time error Now, let’swrite the method slightly differently:

Function ComputeAvg(ByVal Param1 As Object, ByVal Param2 As Object) As Object

ComputeAvg = (Convert.ToInt32(Param1) + Convert.ToInt32(Param2)) / 2End Function

The second version of ComputeAvg() is still valid, but you have forcefully stripped away thetype information You could pass in String, Boolean, or Customer objects, and you wouldn’treceive an error until run time when the function attempts to convert the parameters This isbecause every object and value in VB derives from System.Object The Object keyword in VB

is an alias for the class System.Object It’s perfectly valid to declare parameters as type Object;however, Object is not a numeric type In order to perform the calculation, you must first

“cast” the objects into integers The result is also returned as an instance of type Object If you attempt to pass two Customer objects, the compiler won’t return an error because thoseobjects both derive from System.Object, as every other class does Although this version of themethod seems more flexible, this flexibility comes at the price of type safety and performance.Needless to say, it’s always best to find bugs at compile time rather than run time If youwere to use the first version of ComputeAvg() and try to pass in anything other than integers,you wouldn’t be able to compile the application Type safety is one of the tenets of develop-ment in NET, and the language is designed to support it

The reason I say that VB can be strongly typed is that, in contrast to C#, it supports

unde-clared variables This means you can reference a variable without first declaring it with a Dim, Private, or Public declaration VB will create any undeclared variables as type Object The two settings that affect strong typing and variable declaration in VB are Option Explicitand Option Strict

Option Explicit: Option Explicit enforces the declaration of variables When OptionExplicit is set On within a file, any variable must be explicitly declared If Option Explicit

is On and you have an undeclared variable, you’ll receive a compiler error If OptionExplicit isn’t specified in the file, the compiler default is On In this snippet, you’ll receive

a compiler error on the last line, because the variable VarUndeclared is not declared where If Option Explicit was Off, both the variables VarDeclared and VarUndeclaredwould be valid When this code compiles, VB will define VarUndeclared as type Objectuntil it’s assigned, at which point it will implicitly convert it to a Double because of its dataassignment:

any-Option Explicit On

…Dim VarDeclared As Double

Trang 8

VarDeclared = ComputeAvg(108, 7933)VarUndeclared = ComputeAvg(108, 7933)Option Strict: The Option Strict setting is related to any implicit data conversions that

VB performs on variables Option Strict only allows widening conversions If OptionStrict is On, VB will only allow variables to be converted from one data type to anotherdata type in which no data loss would occur If a variable is being converted and theresultant type has less precision or smaller capacity, a compiler error will be generated

Option Strict also disallows late binding If Option Strict isn’t specified, the compilerdefault is Off Using the second ComputeAvg function shown previously, you can see thatthe following code will fail at compile time because Option Strict won’t allow an implicitconversion from Object to Double If Option Strict was Off, this code would compile andrun:

Option Strict On

…Dim x As Double = 0.0

x = ComputeAvg(108, 7933)Function ComputeAvg(ByVal Param1 As Object, ByVal Param2 As Object) As ObjectComputeAvg = (Convert.ToInt32(Param1) + Convert.ToInt32(Param2)) / 2End Function

You should always keep Option Explicit and Option Strict set to On in your tions, primarily because you’ll avoid having to debug some devious errors that only appear at

applica-run time This practice ensures that your code is strongly typed and is consistent with the type

safety of other NET languages

Note In VB6, you may have used the Variantdata type to store and pass parameters of different data

types, because a Variantvariable can hold data of any type Also, if you used undeclared variables, VB6

would create them as Variant This data type is no longer supported in NET, and the Objecttype is used

instead

Type Categories

Every entity in a VB program is an object that lives in memory on either the stack or the

man-aged heap Where an entity is allocated depends on whether it’s a value type or a reference

type Every method is defined in a class or module declaration (which is really a class under

the hood) Even the built-in value types, such as Integer, Long, and Double, implicitly have

methods associated with them In VB, it’s perfectly valid to write a statement such as this:

Console.WriteLine(108.ToString())

Trang 9

This statement returns the string value "108" A statement like this seems unfamiliar ifyou’re used to programming in VB6 However, this syntax emphasizes how everything in VB is

an object, even down to the most basic types In fact, the keywords for the built-in types in VBare actually aliases that are mapped directly into types in the System namespace You can electnot to use the built-in VB types and explicitly use the types in the System namespace, but thispractice is discouraged as a matter of style Table 3-1 lists the built-in types with their size andcorresponding types in the System namespace

Table 3-1.VB Intrinsic Types

of the CTS and is designed to foster language interoperability by defining the features that arestandard across each language This is needed because even though the CLR supports a richset of built-in types, not all languages that create managed code support all other languagetypes For example, in the past, VB didn’t support unsigned types, whereas C# did So thedesigners of the CLI defined the CLS to standardize types and facilitate interoperabilitybetween the languages

If your application will be entirely VB-based and won’t create any components consumedfrom another language, then you don’t have to worry about adhering to the strict guidelines ofthe CLS But if you work in a project that builds components using various languages or youknow there’s a chance that your components will be called from other languages in the future,then conforming to the CLS is much more of a consideration

Trang 10

In the managed world of the CLR, any data type must be one of two kinds of types:

Value type: In VB, a value type can be any one of the intrinsic data types, a structure, or an

enumeration Value types live on the memory stack, which is much faster to accessbecause the type’s value is actually stored in the stack and can be popped off the stackwhen the type variable goes out of scope A value type variable resides on the managedheap if it contains a reference type or if the type is boxed (we’ll cover boxing later in thischapter in the “Boxing” section)

Reference type: A reference type is defined in VB using the Class keyword It is called a reference type, because a reference type variable actually contains a reference to the object

on the managed heap instead of the object itself

Value Types

Value types typically reside in the memory stack and are commonly used when you need to

represent data that is generally small in its memory footprint Value types are efficient, and

when a value type variable goes out of scope, it’s immediately removed from the stack Not

surprisingly, value types are passed by value by default

The most common value types are the built-in data types such an Integer, Boolean, andDouble When you create a value type during the flow of execution, the value is created on the

stack, as shown in this code snippet:

Dim TheAnswer As Integer = 42

Console.WriteLine(TheAnswer.ToString)

Not only is the TheAnswer instance created on the stack, but if it’s passed to a method, themethod receives a copy of the value You can define user-defined value types in VB by using

the Structure keyword, as shown in the following snippet User-defined value types behave in

the same way that the built-in value types do:

Public Structure Coordinate 'This is a value type

Dim x As IntegerDim y As IntegerEnd Structure

Values can live on the managed heap, but not by themselves One way this can happen is

if a reference type contains a value type Even though a value type inside of an object lives on

the managed heap, it still behaves the same as a value type on the stack when it comes to

passing it into a method; that is, the method will receive a copy by default Any changes

made to the value instance are only local changes to the copy unless the value was passed

by reference The following code illustrates these concepts:

Module Module1

Public Structure Coordinate 'this is a value typeDim x As Integer

Dim y As IntegerEnd StructurePublic Class EntryPoint 'this is a reference type

Trang 11

Public Function AttemptToModifyCoord(ByVal Coord As Coordinate) As BooleanCoord.x = 1

Coord.y = 3Return TrueEnd FunctionPublic Function ModifyCoord(ByRef Coord As Coordinate) As BooleanCoord.x = 10

Coord.y = 10Return TrueEnd FunctionEnd ClassSub Main()Dim Location As New CoordinateDim EP As New EntryPointLocation.x = 50

Location.y = 50EP.AttemptToModifyCoord(Location)System.Console.WriteLine("( {0}, {1} )", Location.x, Location.y)EP.ModifyCoord(Location)

System.Console.WriteLine("( {0}, {1} )", Location.x, Location.y)End Sub

End Module

In the Main method, the call to AttemptToModifyCoord actually does nothing to the Location.x and Location.y values This is because in the AttemptToModifyCoord method, theLocation parameter is passed by value and the method modifies a local copy of the structurethat was made when the method was called On the contrary, the Location parameter ispassed by reference to the ModifyCoord method Thus, any changes made in the ModifyCoordmethod are actually made on the Location value in the calling scope The output from theexample is as follows:

Trang 12

customer types throughout your code, you can create an Enum and map the customer type ID

to a name like this:

Enum CustomerType As Integer

Individual = 1Corporate = 2HomeBusiness = 3Federal = 4End Enum

Note that the values don’t have to be in any sequential order Each constant that’s defined

in the enumeration must be defined with a value within the range of the underlying type If a

value is not specified for an enumeration constant, it takes the default value of 0 (if it’s the first

constant in the enumeration) or the value of the previous constant plus 1 This example is an

enumeration based upon a Long:

Enum Color As Long

RedGreen = 50BlueEnd Enum

In this example, if you had left off the Long keyword after the Color type identifier, theenumeration would have been of type Integer In this Enum, the value for Red is 0, the value

for Green is 50, and the value for Blue is 51 To use this enumeration, write the following:

Module Module1

Enum Color As LongRed

Green = 50BlueEnd EnumSub Main()Dim SystemColor As Color = Color.RedSystem.Console.WriteLine("Color is {0}", SystemColor.ToString)End Sub

End Module

If you compile and run this code, you’ll see that the output saysColor is Red

and it actually uses the name of the enumeration rather than the ordinal value 0 This magic is

done by the System.Enum type’s implementation of the ToString method, which returns the

color’s name

Trang 13

Note The underlying type of the Enummust be an integral type that is one of the following:Byte,SByte,Short,UShort,Integer,UInteger,Long, or ULong.

When referring to Enum members, you typically precede the member name with the Enumname However, if you use the Imports statement with your Enum, you can then refer to theEnum members without their fully qualified names, like this:

initial-a different locinitial-ation in memory, initial-and the GC ensures thinitial-at vinitial-ariinitial-ables thinitial-at reference those objectsare updated

Reference types can also be initialized by assignment from another variable of a ble type as in the following code snippet, which creates two reference type variables:

compati-Public Class Coordinate

Dim x As IntegerDim y As IntegerEnd Class

Dim Point1 As Coordinate = New Coordinate

Dim Point2 As Coordinate = Point1

In the example, the value of Point1 and Point2 is a pointer to the Coordinate object cated on the heap If you passed Point1 into a function that updated x and y, you would seethose changes in Point2 as well

allo-■ Note Conventionally, the term object refers to an instance of a reference type, and the term value refers to

an instance of a value type Regardless of what you call them, all instances of any type derive from typeObject

In the managed environment of the CLR, the GC automatically handles all agement tasks, including the creation and destruction of objects This frees you from having toworry about explicitly deleting objects and minimizes memory leaks At any point in time, the

memory-man-GC determines how many references exist to a particular object on the heap If it determinesthere are none, it starts the process of destroying the object on the heap The previous code

Trang 14

snippet contains two references to the same object The first one, Point1, is initialized by

cre-ating a new Coordinate object The second one, Point2, is initialized from Point1 The GC

won’t collect the Coordinate object on the heap until both of these references are outside any

usable scope Table 3-2 provides a summary of the differences between value types and

refer-ence types

Table 3-2.Comparison of Value Types and Reference Types

Represents simple values Represents more complex data structures

Declared using a Dim, Private,or Publicstatement Declared calling a class constructor

Initialized to 0or empty value by default Initialized to Nothingby default

Must always have a value Can have Nothingas a value

By default, passed by value By default, passed by reference

Value contains an actual value Value is a pointer to an object in memory

When passed as a parameter

A copy of the value is made A copy of the reference to the memory

location is made

Garbage Collection

Removed from the stack by the Destructors are called by the GC,

GC when it goes out of scope and the object is removed from the heap

by the GC when it goes out of scope

Type Conversion

Now that you have a good understanding of types in the NET world, let’s take a look at

con-verting instances of one type to another In some cases, this conversion is done implicitly by

the compiler when the value being converted won’t lose any precision or magnitude As you

saw in the discussion of Option Strict, this is known as a widening conversion In the case of

the following ComputAvg function, you can see that the function takes Integer parameters, but

when you pass in parameters of type Short, there’s no compiler error The compiler

automati-cally converts Param1 and Param2 to integers because there’s no danger that the value of a Short

(with a maximum value of 32,767) will be too large to fit in an Integer (with a maximum value

of 2,147,483,647):

Function ComputeAvg(ByVal Param1 As Integer, ByVal Param2 As Integer) As Double

ComputeAvg = (Param1 + Param2) / 2End Function

Dim Param1 As Short = 108

Dim Param2 As Short = 123

ComputeAvg(Param1, Param1)

Trang 15

Note In Visual Studio 2005, the Option Strictsetting defaults to Off, but I recommend settingOption Strictto Onat the project level This ensures that you find any implicit data conversion errors atcompile time, and any narrowing data type conversions will require explicit conversion.

In cases where precision could be lost, an explicit conversion is required In VB, you havetwo options when performing an explicit conversion: you can use the VB conversion functionssuch as CStr or the System.Convert class functions such as Convert.ToString Table 3-3 liststhe functions available for explicit conversions

Table 3-3.Data Type Conversion Functions

VB Function Convert Function Description

array of Unicode characters

value

precision floating point value (Double)

value

value

precision floating point value (Single)

integer value (UInteger)

long value (ULong)

short value (UShort)

Trang 16

Casting variables with either of these methods is pretty straightforward, as this code snippet shows:

Dim StringValue As String = "123"

Dim IntegerValue As Integer

IntegerValue = CInt(StringValue)

Deciding whether to use the conversion functions or the Convert class methods is strictly

a matter of style The Convert class makes code more consistent with data type conversions in

C#, which doesn’t have functions such as CStr The Convert class is found in the System

name-space, and the methods are called like this:

Dim StringValue As String = "123"

Dim IntegerValue As Integer

IntegerValue = Convert.ToInt32(StringValue)

Note that if the conversion causes a loss in magnitude, it’s possible that the conversionmay throw an exception at run time For example, if you tried to convert the string

"746475959658567" to an Integer, you would receive an overflow error because that value

exceeds the maximum value that an integer can contain

CType

You’ve seen how to convert value types in VB, but another common need is to convert

refer-ence types from one type to another A base class can be implicitly cast to a derived type,

because the derived type inherits from the base class However, a derived class must be

explic-itly cast to a base type using the CType function Essentially, CType converts the specified

expression to the specified data type, object, structure, class, or interface, and the syntax is as

follows:

CType(expression, typename)

In examining how to cast reference types, assume you have a Coordinate class and aGraphCoordinate class that inherits from and extends the Coordinate class You also have a

PrintCoordinates function that sends the x and y values to the console:

Public Class Coordinate

Public x As IntegerPublic y As IntegerEnd Class

Public Class GraphCoordinate

Inherits CoordinatePublic PointDesc As StringEnd Class

Trang 17

Public Function PrintCoordinates(ByVal Coord As Coordinate) As Boolean

System.Console.WriteLine("( {0}, {1} )", Coord.x, Coord.y)Return True

End Function

As we said before, a base class can always be cast to a derived type Therefore, it’s possible

to implicitly cast any value to an Object because all types derive from Object The followingcode snippet won’t cause any errors:

Dim Coord As New Coordinate

Coord.x = 10

Coord.y = 50

Dim oCoord As Object = New Coordinate

Now let’s define the GraphCoordinate instance and then attempt to call the PrintCoordinates function:

Dim GraphCoord As New GraphCoordinate

Option Strict On, the third call results in a compiler error, disallowing the implicit conversion

of oCoord to the Coordinate class In order to pass oCoord as a parameter, you must “cast itdown” to the Coordinate type like this:

PrintCoordinates(CType(oCoord, Coordinate))

Another keyword related to reference type conversion is TypeOf Use TypeOf before using CType to determine if you can successfully convert the object Prior to calling the PrintCoordinates method, you could check the type of the oCoord variable and then call the method:

If TypeOf (oCoord) Is Coordinate Then

PrintCoordinates(CType(oCoord, Coordinate))End If

DirectCast and TryCast

New to the latest version of VB are two keywords related to casting reference types: DirectCastand TryCast The DirectCast function is used to cast reference types just like CType and has asimilar syntax:

DirectCast(expression, Type)

Trang 18

However, DirectCast offers better performance because it directly attempts to convert thespecified type, and if it can’t, it throws an exception The command var = CType("123",

Integer) attempts to convert "123" even though it’s a string, and this statement succeeds

because VB will implicitly cast "123" to an Integer But the command var =

Direct-Cast("123", Integer) will fail because the compiler won’t try any implicit conversions and

attempts to directly convert a string to an Integer It’s recommended to use DirectCast when

you know a reference type conversion will work and you need the extra performance benefit

Another difference between CType and DirectCast is that you can only use DirectCast on

types that have an inheritance relationship Therefore, you can’t use DirectCast on value

types, including structures

The TryCast function has the same syntax as DirectCast and performs the same referencetype conversion However, if the cast fails, the function returns Nothing instead of throwing an

error So instead of handling errors from CType or DirectCast, you can use TryCast and check

for Nothing In this code snippet, TryCast attempts to convert reference type x to a type of

EntryPoint This conversion would normally cause an exception, but with TryCast, you simply

check for the result of the conversion:

Dim y As Object = TryCast(x, EntryPoint)

Another common type of conversion is a boxing conversion Boxing is required when a value

type must be assigned to a variable as a reference type To accomplish this type of conversion,

simply declare an object and set its value to that of the value type variable When you do this,

an object is allocated dynamically on the heap that contains the value of the value type

Chapter 4 covers boxing in VB extensively The following code demonstrates boxing:

Module Module1

Sub Main()Dim EmployeeID As Integer = 303Dim BoxedID As Object = EmployeeIDDim UnboxedID As Integer = CInt(BoxedID)EmployeeID = 404

System.Console.WriteLine(EmployeeID.ToString())System.Console.WriteLine(UnboxedID.ToString())End Sub

Trang 19

is bridged between the value type and the reference type worlds within the CLR The BoxedIDobject actually contains a copy of the EmployeeID value This point is demonstrated in thesnippet when the original EmployeeID value is printed after the boxing operation Before print-ing out the values, you unbox the value and copy the value contained in the object on theheap back into another Integer on the stack Unboxing is the opposite action to boxing and isthe process of converting the reference type variable back to a value type variable on the stack.

Reference Type Operators

Although we’ll look at the VB operators in-depth in Chapter 4, there are some operators thatare helpful specifically when working with reference types Given the fact that explicit conver-sions can fail and throw exceptions, times arise when you want to test the type of a variablefirst instead of performing a cast and seeing whether or not it fails The Is operator in con-junction with the TypeOf keyword returns a Boolean that determines if you can convert thegiven expression to the given type as either a reference conversion or a boxing or unboxingoperation For example, consider the following code:

Public Class BaseType

Public x As IntegerPublic y As IntegerEnd Class

Public Class DerivedType

Inherits BaseTypePublic DT1 As LongPublic Description As StringEnd Class

Module Module1

Sub Main()Dim DerivedObj As DerivedType = New DerivedType()Dim BaseObj1 As BaseType = New BaseType()

Dim BaseObj2 = DerivedObj

If TypeOf BaseObj2 Is DerivedType ThenConsole.WriteLine("BaseObj2 {0} DerivedType", "is")Else

Console.WriteLine("BaseObj2 {0} DerivedType", "isnot")End If

If TypeOf BaseObj1 Is DerivedType ThenConsole.WriteLine("BaseObj1 {0} DerivedType", "is")Else

Console.WriteLine("BaseObj1 {0} DerivedType", "isnot")End If

If TypeOf DerivedObj Is BaseType Then

Trang 20

Console.WriteLine("DerivedObj {0} BaseType", "is")Else

Console.WriteLine("DerivedObj {0} BaseType", "isnot")End If

Dim j As Integer = 123Dim Boxed As Object = jDim Obj As Object = New Object()

If TypeOf Boxed Is Integer ThenConsole.WriteLine("Boxed {0} Integer", "is")Else

Console.WriteLine("Boxed {0} Integer", "isnot")End If

If TypeOf Obj Is Integer ThenConsole.WriteLine("Obj {0} Integer", "is")Else

Console.WriteLine("Obj {0} Integer", "isnot")End If

If TypeOf Boxed Is ValueType ThenConsole.WriteLine("Boxed {0} System.ValueType", "is")Else

Console.WriteLine("Boxed {0} System.ValueType", "isnot")End If

End SubEnd Module

The output from this code is

Two related operators that are useful when working with reference types are Is and IsNot

The syntax for these operators looks like this:

BooleanResult = Object1 Is Object2

These two operators return a Boolean value after comparing the first object to see if itrefers to the same object as the second Note that the Is/IsNot operators only consider

Trang 21

reference types, and VB will generate a compiler error if you try to use Is/IsNot with valuetypes Here’s a code example using the Is operator:

Dim ObjectA As New Object

Dim ObjectB As New Object

Dim ObjectC As New Object

Dim ObjectD As New Object

Dim IsObject As Boolean

ObjectA = ObjectC

ObjectB = ObjectC

IsObject = ObjectA Is ObjectC

IsObject = ObjectB Is ObjectC

IsObject = ObjectB Is ObjectA

IsObject = ObjectC Is ObjectD

The first three comparisons result in True because ObjectA and ObjectB both refer toObjectC The third comparison is the most interesting because even though ObjectA andObjectB have no relationship to each other through direct assignment, they both refer toObjectC and therefore are the same as each other The final comparison results in Falsebecause ObjectD is not assigned anywhere

Namespaces

Namespaces are used to organize your types within an assembly and help you avoid namingcollisions between your identifiers Using namespaces, you define all of your types such thattheir identifiers are qualified by the namespace that they belong to You’ve already seen name-spaces in action in many of the examples so far For example, in the Hello World! examplefrom Chapter 1, you saw the use of the Console class, which lives in the NET Framework ClassLibrary’s System namespace and whose fully qualified name is System.Console It’s a goodpractice to organize your components with namespaces, and the general recommendation is

to use some sort of identifier such as your organization’s name as the top-level namespaceand then more specific library identifiers as nested namespaces

Namespaces provide an excellent mechanism for making your types more discoverable,especially if you’re designing libraries meant for consumption by others For example, you cancreate a general namespace such as MyCompany.Widgets where you put the most commonlyused types of widgets Then you can create a MyCompany.Widgets.Advanced namespace whereyou place all of the less commonly used, advanced types Sure, you could place them all in onenamespace However, it’s much easier for consumers of your libraries to see the types logicallyarranged with the commonly used ones separated from the less commonly used types

Note Within a namespace, you can define “container” items such as modules, interfaces, classes, gates, enumerations, structures, and nested namespaces You cannot have properties, procedures, variables,

dele-or events within a namespace

Ngày đăng: 09/08/2014, 12:22