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

Professional C# Third Edition phần 3 pps

140 371 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

Định dạng
Số trang 140
Dung lượng 4,38 MB

Nội dung

With the exception of the basic System.Array, all the data structure classes are located in the System. Collections namespace. The name System.Collections reflects another of those terminology ambiguities that plague comput- ing. Collection is often used informally to denote any data structure. However, it also has the more specific meaning of a class that implements IEnumerable or ICollection—a particular type of data structure that we will investigate later in this chapter. In this chapter, we will always use the term collection to refer to the more specific meaning, except where .NET base class names force us to use it in the general sense. Array Lists An array list is very similar to an array, except that it has the ability to grow. It is represented by the class System.Collections.ArrayList. The ArrayList class also has some similarities with the StringBuilder class. Just as a StringBuilder allocates enough space in memory to store a certain number of characters, and allows you to manipulate characters within the space, the ArrayList allocates enough memory to store a certain number of object references. You can then efficiently manipulate these object references . If you try to add more objects to the ArrayList than permitted, then it will automatically increase its capacity by allocating a new area of memory big enough to hold twice as many elements as the current capacity, and relocate the objects to this new location. You can instantiate an array list by indicating the initial capacity you want. For this example, we will assume we are creating a list of Vectors: ArrayList vectors = new ArrayList(20); If you don’t specify the initial size, it defaults to 16: ArrayList vectors = new ArrayList(); // capacity of 16 You can then add elements using the Add() method: vectors.Add(new Vector(2,2,2)); vectors.Add(new Vector(3,5,6)); The ArrayList treats all its elements as object references. That means you can store whatever objects you like in an ArrayList, but when accessing the objects, you will need to cast them back to the appro- priate data type: Vector element1 = (Vector)vectors[1]; This example also shows that ArrayList defines an indexer, so that you can access its elements with an array-like syntax. You can also insert elements into the ArrayList: vectors.Insert(1, new Vector(3,2,2)); // inserts at position 1 There is also a useful override of Insert that allows you to insert all the elements of a collection into an ArrayList, given an ICollection interface reference. 240 Chapter 9 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 240 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com You can remove elements: vvectors.RemoveAt(1); // removes object at position 1 You can also supply an object reference to another method, Remove().However, this takes longer since it will cause the ArrayList to make a linear search through the array to find the object. Note that adding or removing an element causes all subsequent elements to have to be correspondingly shifted in memory, even if no reallocation of the entire ArrayList is needed. You can modify or read the capacity with the Capacity property: vectors.Capacity = 30; Note, however, that changing the capacity causes the entire ArrayList to be reallocated to a new block of memory with the required capacity. The number of elements in the ArrayList can be obtained with the Count property: int nVectors = vectors.Count; An array list can be really useful if you need to build up an array of objects but you do not know in advance how big the array is going to be. In that case, you can construct the array in an ArrayList, and then copy the ArrayList back to a plain old array when you have finished, provided that you actually need the data as an array (this would be the case, for example, if the array is to be passed to a method that expects an array as a parameter). The relationship between ArrayList and Array is in many ways similar to that between StringBuilder and String. Unfortunately, unlike the StringBuilder class, there is no single method to do this conversion from an array list to an array. You have to use a loop to manually copy back references. Note, however, that you are only copying the references not the objects, so this should not result in much of a performance hit: // vectors is an ArrayList instance being used to store Vector instances Vector [] vectorsArray = new Vector[vectors.Count]; for (int i=0 ; i< vectors.Count ; i++) vectorsArray[i] = (Vector)vectors [i]; Collections The idea of a collection is that it represents a set of objects that you can access by stepping through each element in turn. In particular, it is the set of objects that you access using a foreach loop. In other words, when you write something like the following code, you are assuming that the variable messageSet is a collection. foreach (string nextMessage in messageSet) { DoSomething(nextMessage); } The ability to use a foreach loop is the main purpose of collections. They offer little in the way of addi- tional features. 241 Collections 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 241 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Over the next couple of pages, we are going to look in more detail at what a collection is and implement our own collection by converting our Vector example. The broad concepts behind collections are actu- ally not new to the .NET Framework. Collections have been a part of COM for years and have also been used in Visual Basic 6 with the convenient For Each syntax. Java also has a foreach loop, and in both cases the underlying architecture is very similar to that for .NET collections. What is a collection? Internally, an object is a collection if it is able to supply a reference to a related object, known as an enu- merator, which is able to step through the items in the collection. More specifically, a collection must implement the interface System.Collections.IEnumerable. IEnumerable defines just one method and looks like this: interface IEnumerable { IEnumerator GetEnumerator(); } The purpose of GetEnumerator() is to return the enumerator object. As you can gather from the previous code, the enumerator object is expected to implement an interface, System.Collections.IEnumerator. There is an additional collections interface, ICollection, which is derived from IEnumerable. More sophisticated collections will implement this interface as well. Besides GetEnumerator(), it implements a property that returns the number of elements in the collection. It also features support for copying the collection to an array and can supply information indicating if it is thread-safe. However, here we will only consider the simpler collection interface, IEnumerable. IEnumerator looks like this: interface IEnumerator { object Current { get; } bool MoveNext(); void Reset(); } IEnumerator is intended to work like this: the object that implements it should be associated with one particular collection. When this object is first initialized, it does not yet refer to any elements in the collec- tion, and you must call MoveNext(), which moves the enumerator so that it refers to the first element in the collection. You can then retrieve this element with the Current property. Current returns an object ref- erence, so you will have to cast it to the type of object you are expecting to find in the collection. You can do whatever you want with that object then move to the next item in the collection by calling MoveNext() again. You repeat this process until there are no more items in the collection—you will know this has hap- pened when the Current property returns null. You can return to the start of the collection by calling the Reset() method at any time. Note that Reset() actually returns to just before the start of the collection so if you call this method, you must call MoveNext() again to get to the first element. You can see from this example that the point of the collection is simply to provide a way of stepping through all the elements when you don’t want to supply an index, and you are happy to rely on the col- lection itself to choose the order in which the elements are returned to you. This usually means that you 242 Chapter 9 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 242 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com are not bothered about the order in which the elements are retrieved, as long as you get to see all of them, although in some cases a particular collection might be instructed to return the elements in a certain order. In one sense, a collection is a very basic type of group of objects, because it does not allow you to add or remove items from the group. All you can do is retrieve the items in an order determined by the collection, and examine them. It is not even possible to replace or modify items in the collection, because the Current property is read-only. The most frequent use of the collection is to give you the syntactical convenience of the foreach loop. Arrays are also collections, as should be obvious because the foreach command works successfully with arrays. For the particular case of arrays, the enumerator supplied by the System.Array class steps through the elements in increasing order of index from zero upwards. In fact, the previous foreach loop in C# is just a syntactical shortcut for writing the following code: { IEnumerator enumerator = MessageSet.GetEnumerator(); string nextMessage; enumerator.MoveNext(); while ( (nextMessage = enumerator.Current) != null) { DoSomething(nextMessage); // NB. We only have read access // toNextMessage enumerator.MoveNext(); } } Note the enclosing curly braces framing the previous code snippet. We have supplied them in order to ensure that this code has exactly the same effect as the earlier foreach loop. If we hadn’t included them, then this code would have differed to the extent that the nextMessage and enumerator variables would have remained in scope after the loop had finished being executed. One important aspect of collections is that the enumerator is returned as a separate object. It should not be the same object as the collection itself. The reason is to allow for the possibility that more than one enumerator might be applied simultaneously to the same collection. Adding collection support to the Vector struct Our Vector struct that we started in Chapter 3 is about to get another extension with collection support. So far our Vector struct contains a Vector instance with three components, x, y, and z, and because we defined an indexer in Chapter 3, it is possible to treat a Vector instance as an array, so that we can access the x-component by writing SomeVector[0], the y-component by writing SomeVector[1], and the z-component by writing SomeVector[2]. We will now extend the Vector struct into a new code sample, the VectorAsCollection project, in which it is also possible to iterate through the components of a Vector by writing code like this: foreach (double component in someVector) Console.WriteLine(“Component is “ + component); 243 Collections 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 243 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Our first task is to mark Vector as a collection by having it implement the IEnumerable interface. We start by modifying the declaration of the Vector struct: struct Vector : IFormattable, IEnumerable { public double x, y, z; Note that the IFormattable interface is present because we added support for string format specifiers earlier. Now we need to implement the IEnumerable interface: public IEnumerator GetEnumerator() { return new VectorEnumerator(this); } The implementation of GetEnumerator() could hardly be simpler, but it depends on the existence of a new class, VectorEnumerator, which we need to define. Since VectorEnumerator is not a class that any outside code has to see directly, we declare it as a private class inside the Vector struct. Its defini- tion looks like this: private class VectorEnumerator : IEnumerator { Vector theVector; // Vector object that this enumerator refers to int location; // which element of theVector the enumerator is // currently referring to public VectorEnumerator(Vector theVector) { this.theVector = theVector; location = -1; } public bool MoveNext() { ++location; return (location > 2) ? false : true; } public object Current { get { if (location < 0 || location > 2) throw new InvalidOperationException( “The enumerator is either before the first element or “ + “after the last element of the Vector”); return theVector[(uint)location]; } } public void Reset() 244 Chapter 9 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 244 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com private class VectorEnumerator : IEnumerator { location = -1; } } As required for an enumerator, VectorEnumerator implements the IEnumerator interface. It also con- tains two member fields, theVector, which is a reference to the Vector (the collection) that this enu- merator is to be associated with, and location, an int that indicates the enumerator’s reference point in the collection—put differently, whether the Current property should retrieve the x, y, or z compo- nent of the vector. The way we will work in this case is by treating location as an index and internally implementing the enumerator to access Vector as an array. When accessing Vector as an array, the valid indices are 0, 1, and 2—we will extend this by using -1 as the value that indicates where the enumerator is before the start of the collection, and 3 to indicate that it is beyond the end of the collection. Hence, the initializa- tion of this field to -1 in the VectorEnumerator constructor: public VectorEnumerator(Vector theVector) { this.theVector = theVector; location = -1; } Notice the constructor also takes a reference to the Vector instance that we are to enumerate—this was supplied in the Vector.GetEnumerator() method: public IEnumerator GetEnumerator() { return new VectorEnumerator(this); } Dictionaries Dictionaries represent a very sophisticated data structure that allows you to access an element based on some key, which can be of any data type you want. They are also known as maps or hash tables. Dictionar- ies are great if you want to store objects as if they were an array, but where you want to use some other data type rather than a numeric type to index into the structure. They also allow you to add and remove items freely, a bit like an ArrayList, but without the performance overhead of having to shift subse- quent items in memory. We will illustrate the kinds of situations in which dictionaries can be useful using the example that we will develop later in this section, the MortimerPhonesEmployees example. This example assumes that Mortimer Phones (the mobile phone company that we first introduced in Chapter 3) has some software that processes details of its employees. To that end, we need a data structure—something like an array— that contains data for employees. We assume that each Mortimer Phones employee is identified by an employee ID, which is a set of characters such as B342 or W435, and is stored as an EmployeeID object. Each employee’s details are stored as an EmployeeData object; for our example, this just contains the employee’s ID, name, and salary. 245 Collections 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 245 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Suppose we have this EmployeeID: EmployeeID id = new EmployeeID(“W435”); and a variable called employees, which we can treat syntactically as an array of EmployeeData objects. In actuality, this is not an array; it is a dictionary, and because it is a dictionary, we can get the details of an employee with the previously declared ID like this: EmployeeData theEmployee = employees[id]; // Note that id is NOT a numeric type – it is an EmployeeID instance That’s the power of dictionaries. They look like arrays (but are more powerful than that; they are more like ArrayLists since you can dynamically set their capacity, and add and remove elements), but you don’t have to use an integer to index into them; you can use any data type you want. For a dictionary, this is called a key rather than an index. Roughly speaking, what happens is that the dictionary takes the key supplied when you access an element (in the previous example this is the ID object) and it does some processing on the value of this key. This processing returns an integer that depends on the value of the key, and is used to work out where in the array the entry should be stored or retrieved from. Here is a short list of other examples where you might want to use a dictionary to store objects: ❑ If you want to store details of employees or other people, indexed by their social security num- bers. Although the social security number is basically an integer, you cannot use an array with social security numbers as the index because a U.S. social security number theoretically can go up to the value of 999999999. On a 32-bit system you’d never fit an array that big in a program’s address space! Most of the array would be empty anyway. Using a dictionary, you can have a social security number to index an employee, but still keep the dictionary size small. ❑ If you want to store addresses, indexed by zip code. In the United States, zip codes are just numbers, but in Canada and the United Kingdom they use letters and numbers together. ❑ If you want to store any data for objects or people, indexed by the name of the object or person. Although the effect of a dictionary is that it looks to client code much like a dynamic array with a very flexible means of indexing into it, there is a lot of work that goes on behind the scenes to bring this about. In principle you can use an object of any class as an index key for dictionaries. However, you must imple- ment certain features on a class before it can be used as a key. This also pertains to the GetHashCode() method that all classes and structs inherit from System.Object. In this section, we will take a closer look under the hood at what a dictionary is, how it works, and how GetHashCode() is involved. Then, we will move on to our MortimerPhonesEmployees example, which demonstrates how to use a dictio- nary and how to set up a class so that it can be used as a key. Dictionaries in real life The term dictionary is used because the structure is very similar to a real-life dictionary’s. In a real dictio- nary you will normally want to look up the meaning of a word (or in the case of a foreign dictionary, the details of how to translate a word). The couple of lines of text that give the meaning (or the translation) are the data you are really interested in. The fact that a large dictionary will have tens of thousands of data items in it is no problem when you want to look up a meaning, because you just look for the word in alphabetical order. In a sense, the word you are looking up is equivalent to the key that you use to get at the data you are really interested in. It is not really the word itself you are interested in so much as the data associated with it. The word just provides the means to locate the entry in the dictionary. This means that there are really three things here that you need to build a dictionary: 246 Chapter 9 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 246 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ❑ The data you want to look up ❑ The key ❑ The algorithm that allows you to find where the data is in the dictionary The algorithm is a crucial part of the dictionary. Just knowing what the key is is not sufficient—you also need a way that you can use the key to find out the location of the item in the data structure. In real-life dictionaries, this algorithm is provided by arranging words in alphabetical order. Dictionaries in .NET In .NET, the basic dictionary is represented by the class Hashtable, which works on the same principles as a real-life dictionary, except that it assumes that the key and item are both of type Object. This means that a Hashtable can store whatever data structure you want. By contrast, a real-life dictionary uses strings as the keys. Although Hashtable represents the generic will-store-anything dictionary, it is permissible to define your own more specialized dictionary classes. Microsoft has provided an abstract base class, DictionaryBase, which provides basic dictionary functionality, and from which you can derive your classes. There is also a ready-made .NET base class, System.Collections.Specialized.StringDictionary, which you should use in place of Hashtable if your keys are strings. When you create a Hashtable object, you can indicate its initial capacity, just as you would for String Builder and ArrayList: Hashtable employees = new Hashtable(53); As usual there are many other constructors, but this is the one you will probably use most often. Notice the unusual size of the initial capacity that we’ve chosen: 53. There is a good reason for this. Due to the internal algorithms used in dictionaries, they work most efficiently if their capacity is a prime number. Adding an object to the Hashtable is done with the Add() method, but Hashtable.Add() takes two parameters, both of them are object references. The first is a reference to the key; the second is a reference to the data. Carrying on with the EmployeeID and EmployeeData classes from the example that we will develop soon: EmployeeID id; EmployeeData data; // initialize id and data to refer to some employee // assume employees is a Hashtable instance //that contains EmployeeData references employees.Add(id, data); In order to retrieve the data for an item, you need to supply the key. Hashtable implements an indexer so that you can retrieve data—this is how we get the array syntax we discussed earlier: EmployeeData data = employees[id]; 247 Collections 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 247 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com You can also remove items from the dictionary by supplying the key of the object to be removed: employees.Remove(id); You can also find out how many items are in the hash table using the Count property: int nEmployees = employees.Count; Notice, however, that there is no Insert() method. We have not yet looked at how a dictionary works internally, but there is no difference between adding and inserting data. Unlike an array or an ArrayList, you don’t find one big block of data at the beginning of the structure and an empty block at the end. Instead, the situation looks more like the diagram in Figure 9-1, in which any unmarked parts of the dic- tionary are empty. Figure 9-1 When you add an entry, it will actually be placed at some location that could be anywhere in the dictionary. How the location is worked out from the key is something that you don’t need to know about when you are using the dictionary. The important point is that the algorithm used to work out the location of an item is reliable. As long as you remember what the key is, you can just hand it to the Hashtable object, and it will be able to use the key to quickly work out where the item is and retrieve it for you. We will examine how the algorithm works later in this section. Hint: It relies on the key’s GetHashCode() method. Note that the above diagram is simplified. Each key/entry pair is not actually stored inside the dictio- nary structure—as is common for reference types, what is stored are the object references that indicate where on the heap the objects themselves are located. How the dictionary works So far, we’ve seen that dictionaries (hash tables) are extremely convenient to use, but there is a snag: Hashtable (and indeed any other dictionary class) uses some sort of algorithm to work out where to DICTIONARY Key + Entry Key + Entry Key + Entry Key + Entry 248 Chapter 9 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 248 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com place each object based on the key, and that algorithm isn’t entirely provided by the Hashtable class. It has two stages, and the code for one of these stages must be provided by the key class. If you are using a class that Microsoft has written, and which can be used as a key (such as String), then there’s no prob- lem (Microsoft will have written all the code already). However, if the key class is one that you have written yourself, then you will have to write this part of the algorithm yourself. In computer parlance, the part of the algorithm implemented by the key class is known as a hash (hence the term hash table), and the Hashtable class looks in a very particular place for the hash algorithm. It looks in your object’s GetHashCode() method, which it inherits from System.Object. Whenever a dictionary class needs to work out where an item should be located, it simply calls the key object’s GetHashCode() method. This is why we emphasized when we were discussing System.Object() that if you override GetHashCode(), there are fairly stringent requirements on how you do it, because your implementation needs to behave in certain ways for dictionary classes to work correctly. (If you don’t intend your class to ever be used as a key in a dictionary, there’s no need to override GetHashCode().) The way it works is that GetHashCode() returns an int, and it somehow uses the value of the key to generate this int. Hashtable will take this int and do some other processing on it that involves some sophisticated mathematical calculations, and which returns the index of where in the dictionary an item with the given hash should be stored. We won’t go into this part of the algorithm—that part has already been coded by Microsoft, so we don’t need to know about it. What you should know is that it involves prime numbers and is the reason why the hash table capacity should be a prime number. For this to work properly, there are some fairly strict requirements for the GetHashCode() override, which we will look at here. These requirements are going to sound quite abstract and daunting, but don’t worry too much. As our MortimerPhonesEmployees example demonstrates, it is not at all diffi- cult to code a key class that satisfies these requirements: ❑ It should be fast (because placing or retrieving entries in a dictionary is supposed to be fast). ❑ It must be consistent; if you regard two keys as representing the same value, then they must give the same value for the hash. ❑ It should ideally give values that are likely to be evenly distributed across the entire range of numbers that an int can store. The reason for this last condition is because of a potential problem; what happens if you get two entries in the dictionary whose hashes both give the same index? If this happens, the dictionary class will have to start fiddling about looking for the nearest available free location to store the second item—and will have to do some searching in order to retrieve this item later on. This is obviously going to hurt performance, and clearly, if lots of your keys are tending to give the same indexes for where they should be stored, this kind of clash becomes more likely. However, because of the way Microsoft’s part of the algorithm works, this risk is minimized when the calculated hash val- ues are evenly distributed between int.MinValue and int.MaxValue. The risk of clashes between keys also increases as the dictionary gets fuller, so it’s normally a good idea to make sure the capacity of the dictionary is substantially greater than the number of elements actually in it. For this reason, Hashtable will automatically relocate in order to increase its capacity well before it actually becomes full. The proportion of the table that is full is termed the load, and you can set the 249 Collections 11 557599 Ch09.qxd 4/29/04 11:33 AM Page 249 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... The example, when run, looks like this: MortimerPhonesEmployees Enter employee ID (format:A999, X to exit)> B001 Employee: B001: Mortimer $100,000.00 Enter employee ID (format:A999, X to exit)> W 234 Employee: W 234 : Arabel Jones $10,000.00 Enter employee ID (format:A999, X to exit)> X This example contains a number of classes In particular, we need the EmployeeID class, which is the key used to identify... EmployeeID { private readonly char prefix; private readonly int number; public EmployeeID(string id) { prefix = (id.ToUpper())[0]; number = int.Parse(id.Substring(1 ,3) ); } public override string ToString() { return prefix.ToString() + string.Format(“{0 ,3: 000}”, number); } public override int GetHashCode() { return ToString().GetHashCode(); } public override bool Equals(object obj) { EmployeeID rhs = obj as... just assume the string passed into the constructor is in the correct format The ToString() method simply returns the ID as a string: return prefix.ToString() + string.Format(“{0 ,3: 000}”, number); Note the format specifier (3: 000) that ensures the int containing the number is padded with zeros, so we get for example B001, and not B1 Now we come to the two method overrides that we need for the dictionary... fields from giving the same hash code) The following snippet shows a suitable implementation of GetHashCode(): public override int GetHashCode() // alternative implementation { return (int)prefix* 13 + (int)number* 53; } This particular example, will work more quickly than the ToString()-based algorithm that we use in the example, but has the disadvantage that the hash codes generated by different EmployeeIDs... sb.ToString(); } } 2 53 Chapter 9 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Notice how once again for performance reasons, we use a StringBuilder object to generate the string representation of an EmployeeData object Finally, we create the test harness This is defined in the TestHarness class: class TestHarness { Hashtable employees = new Hashtable (31 ); public void Run()... when it encounters an element in your code that has a custom attribute applied to it To take our database example, suppose you have a C# property declaration that looks like this: [FieldName(“SocialSecurityNumber”)] public string SocialSecurityNumber { get { // etc When the C# compiler recognizes that this property has an attribute applied to it (FieldName), it will start by appending the string Attribute... Chapter 9 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com The first part of the class definition simply stores the actual ID Remember that the ID takes a format such as B001 or W 234 In other words, it consists of a single letter prefix, followed by three numeric characters We store this as a char for the prefix and an int for the remainder of the code The constructor simply takes... happening For example, you might place an object in the hash table and then discover that you can never retrieve it, or you might try to retrieve an entry and get the wrong entry returned For this reason, the C# compiler will display a compilation warning if you supply an override for Equals() but don’t supply an override for GetHashCode() For System.Object this condition is true, because Equals() simply compares... Hashtable (31 ); public void Run() { EmployeeID idMortimer = new EmployeeID(“B001”); EmployeeData mortimer = new EmployeeData(idMortimer, “Mortimer”, 100000.00M); EmployeeID idArabel = new EmployeeID(“W 234 ”); EmployeeData arabel= new EmployeeData(idArabel, “Arabel Jones”, 10000.00M); employees.Add(idMortimer, mortimer); employees.Add(idArabel, arabel); while (true) { try { Console.Write(“Enter employee... Console.WriteLine(“Employee not found: ID = “ + id); } } TestHarness contains the member field, which actually is the dictionary As usual for a dictionary, we have set the initial capacity to a prime number; in this case, 31 The guts of the test harness are in the Run() method This method first sets up details for two employees—mortimer and arabel—and adds their details to the dictionary: employees.Add(idMortimer, mortimer); . component in someVector) Console.WriteLine(“Component is “ + component); 2 43 Collections 11 557599 Ch09.qxd 4/29/04 11 :33 AM Page 2 43 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Our. “); sb.Append(string.Format(“{0:C}”, salary)); return sb.ToString(); } } 2 53 Collections 11 557599 Ch09.qxd 4/29/04 11 :33 AM Page 2 53 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Notice. Ch09.qxd 4/29/04 11 :33 AM Page 245 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Suppose we have this EmployeeID: EmployeeID id = new EmployeeID(“W 435 ”); and a variable

Ngày đăng: 13/08/2014, 15:21

TỪ KHÓA LIÊN QUAN