Pro Visual C++-CLI And The .NET 2.0 Platform (2006) [eng]-1
.pdf188 |
C H A P T E R 4 ■ A D V A N C E D C + + / C L I |
source->OnSay += gcnew SayHandler(this, &EventReceiver1::SayHello); source->OnSay += gcnew SayHandler(this, &EventReceiver1::SayStuff);
}
void RemoveStuff()
{
source->OnSay -= gcnew SayHandler(this, &EventReceiver1::SayStuff);
}
void SayHello(String ^name)
{
Console::Write("Hello there "); Console::WriteLine(name);
}
void SayStuff(String ^name)
{
Console::Write("Nice weather we are having. Right, "); Console::Write(name);
Console::WriteLine("?");
}
};
ref class EventReceiver2
{
EventSource ^source; public:
EventReceiver2(EventSource ^src)
{
if (src == nullptr)
throw gcnew ArgumentNullException("Must pass an Event Source");
source = src;
source->OnSay += gcnew SayHandler(this, &EventReceiver2::SayBye);
}
void SayBye(String ^name)
{
Console::Write("Good-bye "); Console::WriteLine(name);
}
};
void main()
{
EventSource ^source = gcnew EventSource();
EventReceiver1 ^receiver1 = gcnew EventReceiver1(source);
EventReceiver2 ^receiver2 = gcnew EventReceiver2(source);
source->Say("Mr Fraser");
C H A P T E R 4 ■ A D V A N C E D C + + / C L I |
189 |
Console::WriteLine("-------------------------------"); receiver1->RemoveStuff();
source->Say("Stephen");
}
Figure 4-13 shows the results of this little program.
Figure 4-13. Results of Events.exe
Summary
In this chapter, you looked at some more advanced C++/CLI language topics. You started with the preprocessor directives, and then you moved on to multifile software development. Next, you covered templates, typedef, and exceptions, and finally, you ended with delegates and events.
This chapter covered a lot of new ground for the traditional C++ developer, though much of it had a very familiar flavor to it. You use much of this chapter later in the book, so a good understanding of these topics is essential.
Okay, you have finally covered C++/CLI as a language. In the next chapter, you make your first real foray into the world of .NET software development by looking at the .NET Framework class library.
P A R T 2
■ ■ ■
.NET Framework
Development in C++/CLI
C H A P T E R 5
■ ■ ■
The .NET Framework Class Library
To put it bluntly, the .NET Framework class library is just plain huge. One chapter could never do it justice. There are, in fact, several books devoted solely to describing all the interfaces, structures, enumerations, classes, methods, variables, and so on, that are contained within this library. This chapter’s goal is to focus on giving you a head start in learning how to navigate through this massive library.
Even though the library is big, it is well organized and (gasp!) well documented. Once you understand the basics of how the library is organized, it will be easy for you to locate what you are looking for. It should also be quite simple to figure out if what you are looking for is not included in the library.
I just briefly touch upon the contents of the class library here. In the following chapters, I delve deeper into many specific areas in the library.
Library Organizational Structure
The first thing you need to know about the .NET Framework class library is that it is an object-oriented tree derived from a single root: System::Object. The next important characteristic is that the .NET Framework class library strictly follows the rules specified by the common language specification (CLS), covered in Chapter 1. The key rules that you should be aware of are as follows:
•Global functions and variables are not allowed.
•There is no imposed case sensitivity (a consequence of the need to support languages like Visual Basic .NET), so all exposed types differ by more than their case. In other words, all public or protected members differ by more then just case.
•The primitive types allowed as parameters conform to the CLS, namely, Byte, Int16, Int32,
Int64, Single, Double, Boolean, Char, Decimal, IntPtr, and String.
•Variable-length parameter lists to methods are not allowed. Fixed-length arrays are used as parameters instead.
•Pointers are not allowed.
•Class types must inherit from a CLS-compliant class.
•Only single class inheritance is allowed, although multiple inheritance of interfaces is permitted.
Another important aspect of the .NET Framework class library is that the current version is broken up into nearly 100 namespaces. Unlike many other libraries, the component identifiers used for the namespaces are self-describing and thus have the benefit of making it easy to understand what functionality resides within a namespace.
193
194 C H A P T E R 5 ■ T H E . N E T F R A M E W O R K C L A S S L I B R A R Y
You should be aware that even though namespaces in the .NET Framework class library appear to be broken up into a hierarchy, there is, in fact, no actual “class inheritance hierarchy” that corresponds directly to this “namespace hierarchy.” Instead, the namespaces are simply a way of organizing classes into common functionality groups. For example, there is a “namespace hierarchy” of System::Collections::Specialized, but many of the classes found in the
System::Collections::Specialized namespace don’t inherit from System::Collections.
The .NET Framework class library is physically made up of multiple assembly .dlls, which you have to add references to in your code either using the #using statement or in the program’s reference properties, if using Visual Studio 2005. An assembly does not necessarily correspond directly to a namespace, as an assembly may contain multiple namespaces. Also, some of the namespaces spread across multiple assemblies. This does complicate things, as there is no one-to-one correlation, but the .NET Framework class library has placed the most commonly used classes into one assembly: mscorlib.dll. Then, it spread out the less common classes into assemblies made up of common functionality.
Unfortunately, I know of no way to easily figure out which assembly contains which classes. I’ve tried to help you in this regard by pointing out the necessary assemblies to include for each namespace. The only other way I know of to figure out which assembly is needed (other than looking it up in the
.NET documentation) is to look for the C1190 error when compiling (I suppose “linking” is more accurate). This error tells you which assembly is missing.
Library Namespaces
It’s unlikely that you’ll use every namespace in the .NET Framework class library. (That’s not to say you won’t—it’s just unlikely.) Instead, you’ll probably work with the subset of namespaces described in the sections that follow.
I will start with the root namespace System and then progress alphabetically through the most common namespaces. This chapter will not provide you everything you need to implement the classes within a namespace. Instead, it will give you an understanding of what functionality resides within it. If you want a deeper understanding of all the details of the classes within a namespace
(I do not cover the namespace in the subsequent chapters), then I suggest you peruse the documentation provided with the .NET Framework, as it is remarkably well done.
System
The System namespace is the root of the .NET Framework class library namespace hierarchy. The namespace is defined within the mscorlib.dll assembly.
Unlike the other namespaces of the .NET Framework class library, which focus on a particular area of functionality, the System namespace is more a mishmash of core data types and basic functionality that is needed by the rest of the namespace hierarchy.
The most important class within the System namespace is probably the Object class because it is the root of all other classes found within the class library. When you create C++/CLI ref classes of your own, the Object class is inherited by default if you do not specify a parent class. Remember that because C++/CLI ref classes can only inherit from other C++/CLI ref classes, ultimately your class will inherit the Object class.
Some of the other common functional areas covered by the System namespace are as follows:
•Primitive types, such as Byte, Int32, Double, and String
•Arrays
•Data type conversion
C H A P T E R 5 ■ T H E . N E T F R A M E W O R K C L A S S L I B R A R Y |
195 |
•Attributes
•Delegates
•Enums
•Events
•Exceptions
•Garbage collection
•Math
•Operating system information
•Random numbers
As you can see, you have already covered most of these areas in previous chapters.
Normally, a developer would allow garbage collection to be handled automatically by the CLR, because it’s a well-tuned process. For some applications, there might be occasions when garbage collection simply doesn’t run often enough or at the times wanted by the developer. For these cases, the .NET Framework class library provides the System::GC class. This class doesn’t allow the programmer the ability to change the garbage collection process, but it changes the triggering process and helps determine when memory is garbage collected. As a C++/CLI developer, you will probably have little need for the System::GC class given that you now have deterministic cleanup at your disposal. Other
.NET languages are not so lucky.
The Math class is an important class that I haven’t yet covered. It’s made up of a set of static data type overloaded member methods such as Abs(), Exp(), Max(), and Sin(). These methods are easy to use. For example, to find the square root of a number, simply code the following:
double val = 16;
double root = System::Math::Sqrt( val );
Another class that can come in handy is System::OperatingSystem. This class provides information such as the version and platform identifier. The System::Version class is used to hold the fourpart version (Build, Major, Minor, and Revision) used by the .NET Framework.
Because I am a games program developer at heart, one of the first classes I went in search of was the random-number generator. System::Random provides random numbers in both integer and floating-point formats.
System::Random ^rand = gcnew System::Random();
int intRandomNumber = rand->Next(1, 10); // between 1 and 10 inclusive double doubleRandomNumber = rand->NextDouble(); // between 0.0 and 1.0
System::Collections
There are, in fact, three sets of collections available to the .NET Framework programmer:
System::Collections, System::Collections::Specialized, and System::Collections::Generic. As the namespaces suggest, the first set contains standard collection types, the second contains collection types with a more specific purpose, and the third set contains collections specifically targeting the new generic class introduced in the .NET Framework version 2.0. You will find the more common and frequently used System::Collections in the mscorlib.dll assembly, whereas the
System::Collections::Specialized and System::Collections::Generic are in the system.dll assembly. Because collections are an integral part of most .NET software development, Chapter 7 goes
into many of these collections in much greater detail.
196 C H A P T E R 5 ■ T H E . N E T F R A M E W O R K C L A S S L I B R A R Y
Table 5-1 shows you at a glance what collection types are found in the System::Collections namespace.
Table 5-1. Collection Types Found Within System::Collections
Collection |
Description |
ArrayList |
An array that grows dynamically |
BitArray |
An array of bit values (either 1 or 0) |
Hashtable |
A collection of key/value pairs organized based on a hash code of the key |
Queue |
A collection of first-in-first-out objects |
SortedList |
A collection of key/value pairs sorted by key and accessible by either key or |
|
index value |
Stack |
A collection of first-in-last-out objects |
|
|
Table 5-2 lists all the collection types that you will find in System::Collection::Specialized. As you can see, you will probably use these collections less often, but the .NET Framework class library is nice enough to provide them if you ever end up needing to use one of them.
Table 5-2. Collection Types Found Within System::Collections::Specialized
Collection |
Description |
BitVector32 |
A small collection that will represent Boolean or small integers within |
|
32 bits of memory |
HybridDictionary |
A collection that switches from a list dictionary when small to a hash |
|
table when larger |
ListDictionary |
A singular link list recommended for lists of ten objects or less |
NameValueCollection |
A collection of string key/value pairs organized on the string key and |
|
accessible by either string key or index |
StringCollection |
A collection of strings |
StringDictionary |
A hash table with the key strongly typed to be a string |
|
|
Table 5-3 lists all the collections that you will find in System::Collections::Generic. Most likely, as you become more familiar with generics, these collections will become your primary choice.
■Note After claiming that the .NET Framework strictly adheres to the CLS rules, Microsoft goes ahead and makes me a liar. System::Collections::Generic classes are not CLS compliant. Personally, I think the CLS rules will be expanded to include generics, but we shall see.
C H A P T E R 5 ■ T H E . N E T F R A M E W O R K C L A S S L I B R A R Y |
197 |
Table 5-3. Collection Types Found Within System::Collections::Generic
Collection |
Description |
Collection<T> |
A base class for generic collections from which users are urged to |
|
derive their own specialized container classes. |
Dictionary<K,V> |
A collection of key/value paired generic objects that are organized |
|
based on the key and retrieved as a KeyValuePair<K,V> struct. |
KeyedCollection<K,V> |
A base class for generic collections using key/value pairs from |
|
which users are urged to derive their own specialized container |
|
classes. |
LinkedList<T> |
A doubly (forward and backward) linked list generic objects. |
List<T> |
An array of generic objects that grows dynamically. |
Queue<T> |
A collection of first-in-first-out generic objects. |
ReadOnlyCollection<T> |
A base class for a generic read-only collection from which users |
|
are urged to derive their own specialized container classes. |
|
A collection that is read-only is simply a collection with a wrapper |
|
that prevents modifying the collection. |
SortedDictionary<K,V> |
A collection of key/value paired generic objects that are sorted |
|
based on the key. |
Stack<T> |
A collection of first-in-last-out generic objects. |
|
|
System::Data
The System::Data namespace is the root for all ADO.NET classes found in the .NET Framework class library. ADO.NET is the data access technology written for the .NET Framework and replaces the use of ADO where it is important to remain entirely within .NET. Accessing a database is a very common practice in software development, so you might think that it would be included in the mscorlib.dll default assembly, but you would be wrong. You need to reference two different assemblies. The first is the System.Data.dll assembly, which makes sense now that you know that it’s a separate assembly. The second is the System.Xml.dll assembly. I go into detail about why this assembly is needed in Chapter 12. A simple reason is that ADO.NET uses a lot of XML and exposes member methods that use XML. To include these assemblies, if you don’t recall, simply add these lines to the top of your source:
#using <System.data.dll> #using <System.Xml.dll>
The System::Data namespace comprises most of the classes that make up the ADO.NET architecture. The classes that represent the specific databases to which ADO.NET will connect are missing. These classes are known in ADO.NET-speak as data providers. Currently, ADO.NET supports multiple data providers. The data providers found in the System::Data namespace are the following:
•System::Data::SqlClient: For Microsoft SQL Server database access
•System::Data::SqlClientCe: For Microsoft SQL Server CE Edition database access
•System::Data::Odbc: For ODBC database access
•System::Data::OleDb: For OLE DB database access
•System::Data::OracleClient: For Oracle database access