BuiltIn Reference Types

One of the built-in reference types that Visual Basic .NET and C# provide is the Object class (in C#, object with a lowercase o). Both types are based on the System.Object type described earlier.

Value types have many purposes and allow for the more efficient use of resources. What happens when you want to use a value type as an object? For example, one of the methods of System.Object is ToString, often used for debugging purposes. The process is called boxing variables.

For example, suppose you have an int variable named i and you want to do something with a string representation of that variable. Consider this code fragment:

using System;

class test {

static void Main() {

object box=i;

System.Console.WriteUne(box.ToStringO); System.Console.WriteUne(i.ToStringO); System.Console.WriteLine(box.GetType()); System.Console.WriteLine(i.GetType());

First we assign the integer i the value 5. Next we declare an object named box and assign it the value i. This line internally boxes the simple value type into an object and makes box refer to that reference type variable—hence the term boxing. On the following line, we print to the console (using System.Console.WriteLine)box.ToString(). ToString is a method of object, and the result is what you would expect: a 5 is displayed on the console.

A bit more surprisingly, the next line, which prints i.ToString(), also displays 5 on the console. This case is a bit different because there's not an object in sight and yet calling ToString, a method of object, still does exactly what you would hope. This occurs through the magic of the .NET Framework, which boxes the value type (in this case, the integer i) in an object. Thus, the method is called on the boxed version of the integer variable.

The next two lines use the same principles to display the type of object, using the GetType method of object. Notice that both the explicit boxed version of i held in the box object and the version boxed on the fly implicitly are of type System.Int32. Neither of these methods will likely be used except for debugging, but the ability to have an object contain a reference to any number of different types is useful.

Boxing of a value type implies making a copy of the value being boxed. For example, suppose we added the following lines to the preceding code:

System.Console.WriteLine(box.ToString()); System.Console.WriteUne(i.ToStringO);

The first line (which refers to a copy of i as it existed at the first assignment) will still display 5 on the console, but the second line, which refers to a copy of i boxed just for this statement, will refer to the new value of i and will thus display 12 on the console. This happens because the type being boxed is a value type.

If, on the other hand, we were boxing a reference type, the object would not reference a copy but rather the object, as in the following code:

using System;

class intHolder {

public int i;

class test{

static void Main() {

object box;

intHolder ih = new intHolder(); ih.i=22;

box=ih;

System.Console.WriteLine(((intHolder)box).i.ToString()); System.Console.WriteLine(ih.i.ToString ());

Both calls to System.Console.WriteLine would display 99 because box now refers to the reference type intHolder, not to a copy of it. If the type intHolder were declared as a struct rather than a class, the first line would display 22 because that would be the value of the copy of ih used when ih was boxed in the box object.

Note These examples have been using C#, but the general principles apply to all languages designed to support the .NET runtime. The String class, available in both Visual Basic .NET and C#, provides virtually all the string handling you could ever need. Just as important, the methods offered are identical in both languages, and future supported .NET languages should also provide the same functionality. The following code snippet only hints at the capabilities available within the String class:

Public Module test

Sub Main()

Dim s as String Dim i as integer s="This is a test " System.Console.WriteLine(s & "|")

System.Console.WriteLine(s & "|")

System.Console.WriteLine(i + System.Convert.ToInt32(s)) End Sub

End module

When run, this short program produces the following output: This is a test | This is a test| 50

First a string is created, with lots of trailing spaces. This string is sent to the console, and the result is exactly as you might expect. Next the Trim method is called, and the string is now printed without any spaces between the word "test" and the vertical bar. Next we set s equal to the literal "46". In doing so, notice that the old string ("This is a test") isn't modified by setting s equal to "46" but rather a new copy is created. Strings are immutable—once created, they are not directly modified. There is a StringBuilder class that can be used if it's convenient to directly modify an existing string rather than create a new copy. Situations in which you might make many modifications to a large string might be appropriate places to use the StringBuilder class rather than creating a new string for each modification because the overhead of allocating and freeing a large block repeatedly might cause a performance problem. Finally, we convert the string to an Int32, add it to another integer value, and display the result.

Most Visual Basic programmers are used to working with strings as you've seen here (making assignments directly to variables, with system support for tasks such as trimming strings). However, this isn't something that all C/C++ programmers are used to (although many C++ programmers are using the Standard Template Library's string classes and would thus be accustomed to this kind of convenience).

Essentially, the same code could be written in C#, and just as important, when strings are sent from code in one .NET language to another, there's not the sort of confusion that was possible with traditional Win32 languages. In the course of working with lots of different Win32 programming languages, I've encountered at least three varieties of strings:

■ The zero-terminated string, native to Win32 programming and C/C++

■ The Basic string, or BSTR, native to Visual Basic and COM

■ The length-prefixed string, with a length byte followed by the actual string, native to Pascal

In addition, there are variants of the zero-terminated string that use 2-byte-wide characters (Unicode). The .NET Framework provides a cross-language standard for storing strings.

Other Objects in the .NET Framework

The .NET Framework provides literally hundreds of other classes that enable you to do things that would have previously required dropping to the Win32 API. Table 3-3 lists some of these classes, along with a brief description of what they do.

Other Objects in the .NET Framework

The .NET Framework provides literally hundreds of other classes that enable you to do things that would have previously required dropping to the Win32 API. Table 3-3 lists some of these classes, along with a brief description of what they do.

Table 3-3 : Overview of Some Classes Within the .NET Framework

Object

Description

Microsoft.Win32.Registry

Manipulates the registry.

System.Array

Provides support for arrays, including searching and sorting.

System.Collections

Provides support for

Table 3-3 : Overview of Some Classes Within the .NET Framework

Object

Description

collections

and includes

classes

such as

ArrayList,

BitArray,

and Stack

that make

using data

simpler.

System.Data

Provides

support for

all sorts of

data access,

including

support for

ADO.NET.

(ADO.NET

is covered in

Chapter 8.)

System.DateTime

Provides

support for

working with

dates and

times.

System.Diagnostics

Provides

convenient

support for

writing to

the event

log and for

other

debugging

tasks, as

well as for

accessing

process

information.

System.Net

Provides

support for

the Domain

Name

System

(DNS),

cookies,

Web

requests,

and Web

responses.

System.Net.Sockets

Provides

support for

using

TCP/IP

sockets,

Table 3-3 : Overview of Some Classes Within the .NET Framework

Object

Description

much like

WinSock in

Win32, but

somewhat

cleaner.

System.Reflection

Provides a

managed

view of

loaded

types and

methods, as

well as the

ability to

create and

invoke

types.

System.Threading

Provides

support for

creating and

managing

multiple

threads of

execution.

System.Web.UI

Enables you

to create

controls and

pages that

will appear

in Web

applications.

System.Xml

Provides

support for

XML,

including

Document

Object

Model

(DOM) level

2 core and

Simple

Object

Access

Protocol

(SOAP) 1.1.

Operations That Still Require Dropping to the Win32 API

Operations That Still Require Dropping to the Win32 API

Although the set of objects present in the .NET Framework is rich, there are still occasions in which you'll have to drop to the Win32 API. For example, Memory Mapped Files (MMF) is one feature that as of this writing won't be directly supported within the .NET Framework. MMF allows multiple applications to share data in a convenient way. I've used MMF to allow a Win32 program written in C++ to communicate with another Win32 program written using Borland Delphi. In both languages, the result was a pointer that could be written to and read just like a traditional in-memory pointer.

Both Visual Basic .NET and C# have the ability to call down to the Win32 API as well as to any standard Win32 DLL that you need to call.

Table 3-3 just touches on the capabilities of the .NET Framework classes. Until now, some of the services offered haven't been available even as a standard part of the Win32 environment (for instance, XML support). Other things, such as threading, are supported in a way that makes possible what wasn't possible previously. These threading objects allow Visual Basic programmers to safely use multiple threads of execution. Because these objects execute within a managed context, all the advantages of managed code are there (security and reliability), and you're still able to do most of what you really need to do to build powerful applications.

0 0

Post a comment