Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro Visual C++-CLI And The .NET 2.0 Platform (2006) [eng]-1

.pdf
Скачиваний:
70
Добавлен:
16.08.2013
Размер:
24.18 Mб
Скачать

238C H A P T E R 6 I N T E G R A T E D X M L D O C U M E N T A T I O N

///</code>

///</example>

void exampleTag() {}

///<exception cref="System::OverflowException">

///This method might throw this exception (NOT)

///</exception>

void exceptionTag() {}

///<permission cref="System::Security::PermissionSet">

///Go ahead anyone can access me.

///</permission>

void permissionTag() {}

///<summary>

///Some <c>Program code</c> in a summary

///</summary>

void cTag() {}

///<example>

///Some code in an example tag

///<code>

///A code statement;

///Another code statement;

///</code>

///</example> void codeTag() {}

///<summary>

///<para>This is the first paragraph which spans more than one line

///When the document window is small enough.</para><para>This is the

///next paragraph which started in a new line.</para>

///</summary>

void paraTag() {}

///<summary>

///A bullet list

///<list type="bullet">

///<item> bullet </item>

///<item> bullet </item>

///</list>

///A numbered list

///<list type="number">

///<item> entry 1 </item>

///<item> entry 2 </item>

///<item> entry n </item>

///</list>

///A table

///<list type="table">

///<item>

///<description>row 1 -- column a</description>

///<description>row 1 -- column b</description>

///<description>row 1 -- column c</description>

///</item>

C H A P T E R 6 I N T E G R A T E D X M L D O C U M E N T A T I O N

239

///<item>

///<description>row 2 -- column a</description>

///<description>row 2 -- column b</description>

///<description>row 2 -- column c</description>

///</item>

///</list>

///A definition of terms

///<list type="table">

///<listheader>

///<term>Properties</term>

///<description>Initial Value</description>

///</listheader>

///<item>

///<term>term1 name</term>

///<description>term1 description</description>

///</item>

///<item>

///<term>term2 name</term>

///<description>term2 description</description>

///</item>

///<item>

///<term>termN name</term>

///<description>termN description</description>

///</item>

///</list>

///</summary>

void listTag() {}

///<summary> This is a summary with an <include> tag containing

///a <list type="bullet">

///<include file='document.xml' path='AllDoc/Entry[@num="1"]/*' />

///</summary>

///<include file='document.xml' path='AllDoc/Entry[@num="2"]/*' /> void includeTag() {}

///<summary> This summary references the <paramref name="param1"/>

///parameter of the method

///</summary>

void paramrefTag(int param1) {}

///<summary>

///The basic see tag <see cref="File" />

///The enhanced see tag <see cref="FileInfo">System::IO:FileInfo</see>

///</summary>

void seeTag() {}

///<summary>

///The basic see tag [<seealso cref="File" />] Nothing here

///The enhanced see tag <seealso cref="FileInfo">FileInfo</seealso>

///</summary>

void seealsoTag() {}

};

}

240 C H A P T E R 6 I N T E G R A T E D X M L D O C U M E N T A T I O N

Summary

This chapter described in detail the integrated XML documentation provided by the C++/CLI compiler, beginning with the basics of documentation and the triple slash comment provided by the compiler, followed by each of the standard tags available to the C++/CLI developer. The chapter ended with an examination of the triple slash comment in action in an example that featured every common documentation tag.

In the next chapter, you’ll begin exploring the .NET development and, in particular, the collection functionality provided by the .NET Framework class library.

C H A P T E R 7

■ ■ ■

Collections

Anyone who has been around the coding world for any length of time has more than likely written his or her own collection routine—probably a simply linked list. Newer programmers may not have written one of their own, but instead, in the case of C++ programmers, used the Standard Template Library (STL) version of a linked list. Either way, most programmers have found a need to work with collections. The .NET Framework uses collections as well. Because collections are so common, the

.NET Framework class library provides a large number of different types.

There are, in fact, three primary sets of collections available to the .NET Framework programmer:

System::Collections, System::Collections::Specialized, and System::Collections::Generic. As the names of these 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 type introduced in the .NET Framework version 2.0.

Something to be aware of is that the names of the three namespaces just mentioned seem to imply that the specialized collections and generic collections are inherited from the standard collections, but in fact there is no such relationship. The namespaces are just groupings of different types of collections.

This chapter focuses on the standard collection set shown in Table 7-1 and the generic collection set shown in Table 7-2. However, the .NET Framework class library has many other specific collections scattered throughout the many namespaces—for example,

System::Text::RegularExpressions::Group, System::Security::PermissionSet, System::Web::UI::WebControls::DataKeyCollection, and even System::Array.

Table 7-1. .NET Standard Collection Classes

Collection

Description

ArrayList

An array that grows dynamically

BitArray

An array of bit values (either 1 or 0)

BitVector32

A small collection that will represent Boolean or small integers

 

within 32 bits of memory

CollectionBase

An abstract base class for deriving strongly typed collections

DictionaryBase

An abstract base class for deriving strongly typed collections of

 

key/value pairs

Hashtable

A collection of key/value pairs organized based on a hash code of

 

the key

HybridDictionary

A collection that switches from a ListDictionary when small to a

 

Hashtable when large

241

242 C H A P T E R 7 C O L L E C T I O N S

Table 7-1. .NET Standard Collection Classes (Continued)

Collection

Description

ListDictionary

A singular linked list recommended for lists of ten objects or less

NameValueCollection

A collection string of key/value pairs organized on the string key and

 

accessible by either string key or index

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

StringCollection

A collection of strings

StringDictionary

A Hashtable with the key strong typed to be a string

 

Table 7-2. .NET Generic Collection Classes

 

 

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 object.

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.

 

 

To make things easier for the developer, the .NET Framework class library provides several interfaces (see Table 7-3 for standard and Table 7-4 for generic) that help provide some commonality between the collections. Learning collections is simplified because many of the collections share these interfaces, and once you learn an interface in one collection, it requires little effort to learn it in a second one.

C H A P T E R 7 C O L L E C T I O N S

243

Table 7-3. .NET Standard Collection Interfaces

Interface

Description

ICollection

Defines methods to determine the size, and provide synchronization

 

and enumeration through all nongeneric collections

IComparer

Exposes a method to compare objects of the collection

IDictionary

Defines methods to allow access to key/value pairs within the

 

collection

IDictionaryEnumerator

Exposes methods to access keys and values while enumerating

 

a collection

IEnumerable

Exposes a method to retrieve an object that implements the

 

IEnumerator interface

IEnumerator

Exposes a method to enumerate through a collection

IHashCodeProvider

Exposes a method to provide a custom hash algorithm

IList

Defines methods to add, insert, delete, and access objects using an

 

index

 

 

Note Default implementations of collections in System::Collections::Generic are not synchronized (thread-safe).

Table 7-4. .NET Generic Collection Interfaces

Interface

Description

ICollection<T>

Defines properties to determine the size of the collection and methods to

 

add, remove, copy, and clear elements, as well as check for the existence

 

of elements

IComparer<T>

Exposes a method to compare objects of the collection

IDictionary<K,V>

Defines properties to allow access to key/value pairs within the collection and

 

methods to add and remove elements, as well as check for the existence of

 

elements

IEnumerable<T>

Exposes a method to retrieve an object that implements the IEnumerator<T>

 

interface

IEnumerator<T>

Exposes a method to enumerate through a collection

IList<T>

Defines methods to add, insert, delete, and access objects using an index

 

 

IEnumerable, IEnumerator, and for each

Even though each of the collections in Tables 7-1 and 7-2 is implemented differently internally, all except BitVector32 implement either the IEnumerable or IEnumerable<T> interface. These interfaces expose one member method, GetEnumerator(). This method returns a handle to an object that

244

C H A P T E R 7 C O L L E C T I O N S

implements either the IEnumerator or IEnumerator<T> interface. And both the IEnumerator and IEnumerator<T> interfaces expose member methods that allow all collections to be handled the exact same way if there is a need.

The IEnumerator and IEnumerator<T> interfaces are fairly simple. You call the method MoveNext() to advance the enumerator to the next item in the collection, and then you grab the item out of the Current property. You know you have reached the end of the collection when MoveNext() returns false.

The IEnumerator interface contains one more method called Reset(), which the implementing class should define, that moves the enumerator back to the start of the collection.

Sound simple enough? There is an even easier way to iterate through a collection. Remember the for each statement? It implements all this IEnumerator and IEnumerator<T> stuff for you.

The following code shows equivalent implementation, first using the IEnumerable and IEnumerator interfaces, and then for each. Both are implemented on the same array (which also implements the IEnumerable interface even though it is not a member of System::Collections):

using namespace System;

using namespace System::Collections;

void main()

{

array<int>^ IntList = gcnew array<int> { 1, 2, 3, 4, 5 };

IEnumerable ^collection = (IEnumerable^)IntList; //Not really needed

IEnumerator ^enumerator = collection->GetEnumerator();

Console::WriteLine("IEnumerator\n-----------

");

while (enumerator->MoveNext())

{

int i = (int)enumerator->Current; Console::WriteLine(i);

}

Console::WriteLine("\nfor each\n--------

");

for each (int i in IntList) Console::WriteLine(i);

}

Figure 7-1 shows the results of the IEnum_foreach.exe program.

The choice of which to use is entirely up to you. There are a few occasions when your only choice is to use IEnumerable/IEnumerator. I show an example in HashSortList.cpp later in the chapter. I find for each to be easier to use, and I try to use it whenever possible.

C H A P T E R 7 C O L L E C T I O N S

245

Figure 7-1. Results of IEnum_foreach.exe

Standard Collections

Now that you’ve looked at the major similarity among the .NET Framework class library collections, you’ll take a look at how they differ. You’ll start with the standard, or more common, collections of the class library. There’s nothing new about these collection types, as they’ve been around for quite a long time. What’s different is how the .NET Framework class library implements them and what interfaces the library provides.

ArrayList

If you’ve never coded an array, then you probably haven’t been coding very long. Arrays, with their simple syntax, are the easiest of all collections to work with, especially when you know exactly how much data you’re working with. Unfortunately, they quickly lose their usefulness when the number of data elements is unknown.

The ArrayList is a solution to the shortcomings of the simple array. You get the simple syntax of an array without having to worry about the number of data elements. Well, that’s not quite accurate: you actually get a slightly more complex array syntax, but only after the array is already loaded.

Loading the ArrayList requires member method calls—simple ones, but method calls just the same. Once the ArrayList is loaded, though, you can treat it almost exactly as you would a simple array.

There is nothing difficult about creating an ArrayList; it is simply a standard class. It does have three different constructors. The default takes no parameters. This constructor creates an ArrayList with a starting Capacity of 16:

ArrayList ^alist = gcnew ArrayList();

That doesn’t mean that the ArrayList is restricted to 16; it just means that the first internal array contains space for 16 elements. If the number of elements, also known as the Count, exceeds the Capacity, then the Capacity is doubled or, in other words, the internal array of the ArrayList doubles and the original array is copied to the new, expanded array.

Caution
246 C H A P T E R 7

C O L L E C T I O N S

When the size of the ArrayList exceeds its capacity, the capacity is doubled. This could cause the ArrayList to be larger than is useful. For example, if your capacity is 20,000 and you add a 20,001st element, then the capacity becomes 40,000, which might not be what you want.

The second constructor allows you to set the initial Capacity. This allows you to optimize the loading of the ArrayList, as no doubling of the Capacity need occur if you can restrict the size of the

ArrayList to less than the Capacity.

ArrayList ^alist = gcnew ArrayList(300);

The last constructor allows you to create an ArrayList from another specified collection. This constructor copies the elements from the originating collection and then sets the Capacity and Count to the number of elements copied.

ArrayList ^org = gcnew ArrayList(); //...populate org

ArrayList ^alist = gcnew ArrayList(org);

It is possible to get the Count or Capacity.

int count = alist->Count;

int capacity = alist->Capacity;

It is also possible to change the Capacity of an ArrayList at runtime by changing the Capacity property. If you change the Capacity to 0, the Capacity changes to the default Capacity of 16. Here is how you would code the setting of the capacity to 123:

alist->Capacity = 123;

Caution Setting the Capacity to a value less than the Count of the ArrayList will result in an

ArgumentOutOfRangeException being thrown.

Loading an ArrayList requires the use of member methods. All of the member methods are quite simple to use and self-explanatory. You can append or insert one or a range of elements to an ArrayList. You can also remove a specific element either by index or by specific content, or you can remove a range of elements by index.

alist->Add("One");

array<String^>^ morenums1 = gcnew array<String^> {"Three", "Six"}; alist->AddRange(morenums1);

alist->Insert(1, "Two");

array<String^>^ morenums2 = gcnew array<String^> {"Four", "Five"}; alist->InsertRange(3, morenums2);

alist->Remove("Six"); alist->RemoveAt(1); alist->RemoveRange(0,4); // Index, Count

Once the ArrayList is loaded, it is possible to access the ArrayList in nearly the same way as a simple array. The only difference is that you are accessing a default index property into the ArrayList, instead of accessing the array element directly.

C H A P T E R 7 C O L L E C T I O N S

247

alist[1] = "Three";

for (int i = 0; i < alist->Count; i++)

{

Console::Write("{0} ", alist[i]);

}

Caution Trying to access an ArrayList element that does not exist via the default index property will throw an ArgumentOutOfRangeException.

Note The default index property index starts at 0, just like any other array in C++.

The ArrayList provides a few useful methods that might make your coding life a little easier. For example, it is possible to reverse the order of all the elements of the ArrayList with Reverse().

alist->Reverse();

Another useful method is the Sort() method, which allows you to sort the ListArray.

Alist->Sort();

It is also possible to do a binary search of a sorted ArrayList to search for a specific element. With this method, the element’s index is returned. If the element is not found, then the search method returns a negative number that indicates the index of the next largest object in the ArrayList.

int indx = alist->BinarySearch("Four");

Similar to the binary search, you can do a linear search to check if the ArrayList contains an element. If the search finds the element, it returns true. If not, it returns false.

bool fnd = alist->Contains("One");

Listing 7-1 shows the ArrayList in action and demonstrates many of the functionalities described previously.

Listing 7-1. Working with ArrayLists

using namespace System;

using namespace System::Collections;

void main()

{

ArrayList ^alist = gcnew ArrayList(4); // will double to 8 alist->Add("One");

alist->Add("-"); alist[1] = "Three";

alist->Insert(1, "Two");

array<String^>^ morenums = gcnew array<String^> {"Four", "Five"};

alist->AddRange(morenums);