This appendix provides information about collection classes.
Arrays are relatively simple collection classes that enable you to store and retrieve items by using their indexes in the array. C# provides two kinds of arrays: simple arrays and array objects that are instances of the Array
class.
The syntax for declaring and allocating a one-dimensional array follows.
type[] name = new type[length];
Here type is the data type that the array should hold, name is the name you want to give the array, and length is the number of items the array should hold. The array’s indexes range from 0 to length - 1
.
The syntax for declaring and allocating a two-dimensional array follows.
type[,] name = new type[length1, length2];
The only difference between this declaration and the preceding one is that you need to specify the number of items the array should hold in each dimension. For example, the following statement creates an array of integers with 10 rows and 20 columns.
int[,] values = new int[10, 20];
To make higher-dimensional arrays, use a similar syntax with more commas in the declaration and more lengths in the allocation part.
To initialize an array when it is declared, include the values it should hold inside braces, as in the following code.
int[] primes = { 2, 3, 5, 7, 11 };
To initialize multidimensional arrays, include each dimension’s values inside their own braces. The following code declares and initializes a 2 4 array of integers.
int[,] values =
{
{11, 12, 13, 14},
{21, 22, 23, 24},
};
The Array
class provides another method for creating arrays. Simple arrays give much faster performance than Array
objects, so use them whenever possible.
One reason you may want to use an Array
object is so that you can give the array nonzero lower bounds. The following code creates a two-dimensional Array
object with row indexes ranging from 2001 to 2010 and column indexes ranging from 1 to 4. It then uses the SetValue
method to set the value sales[2005, 3]
.
int[] lengths = {10, 4};
int[] lowerBounds = {2001, 1};
Array sales = Array.CreateInstance(typeof(decimal), lengths, lowerBounds);
sales.SetValue(10000m, 2005, 3);
The following table summarizes some of the most useful Array
class methods.
Property/Method | Purpose |
BinarySearch | Returns the index of an item in the previously sorted array. The items must implement the IComparable interface, or you must provide an IComparer object. |
Clear | Removes all the items from the array. |
ConvertAll | Converts an array of one type into an array of another type. |
Copy | Copies some or all the items from a position in one array to a position in another. |
Exists | Determines whether the array contains a particular item. |
IndexOf | Returns the index of the first item with a given value. |
LastIndexOf | Returns the index of the last item with a given value. |
Resize | Resizes the array. |
Reverse | Reverses the order of the items in the array. |
Sort | Sorts the items in the array. The items must implement the IComparable interface, or you must provide an IComparer object. |
You can use these Array
methods to manipulate simple arrays as well as Array
objects.
Collection classes store items in different data structures so that they can provide special features. For example, dictionaries enable you to use keys to locate objects. The following sections describe collection classes and how to initialize them.
The following list describes classes available in the System.Collections
and System.Collections.Specialized
namespaces.
ArrayList
—A simple resizable array implemented internally as a list.StringCollection
—Similar to an ArrayList
except it can hold only string
s.NameValueCollection
—A collection that can hold one or more string
values for a particular key.System.Collections.Specialized
namespace defines the following dictionary classes.
ListDictionary
—A dictionary that internally stores its items as a linked list. This is good for short lists but not long ones.Hashtable
—A dictionary that internally stores its items in a hash table. This provides fast access but imposes some memory overhead, so it is good for long lists but not short ones.HybridDictionary
—A dictionary that uses a linked list when the number of items is small and a hash table when the number of items is large.StringDictionary
—A dictionary that uses a hash table to store string values with string keys.SortedList
—A combination of Hashtable
and Array
.Stack
—A list that stores and retrieves items in last-in-last-out (LIFO) order.Queue
—A list that stores and retrieves items in first-in-first-out (FIFO) order.The collection classes in the System.Collections.Generic
namespace use generic parameters to provide strong type checking. You should use them instead of the specialized collections described in the preceding section whenever possible. The following list describes these collections and related classes.
Dictionary
—A strongly typed dictionaryLinkedList
—A strongly typed linked listLinkedListNode
—A strongly typed node in a linked listList
—A strongly typed listQueue
—A strongly typed queueSortedDictionary
—A strongly typed sorted dictionarySortedList
—A strongly typed sorted listStack
—A strongly typed stackIf a collection class has an Add
method, you can initialize a new instance of the collection by including values inside braces after the new
statement. The following code initializes a new List<Author>
.
List<Author> authors = new List<Author>()
{
new Author("Terry", "Pratchett"),
new Author("Jasper", "Fforde"),
new Author("Tom", "Holt"),
};
If a class’s Add
method takes multiple parameters, include them in their own braces. The following code initializes a Dictionary<string, string>
.
Dictionary<string, string> phoneNumbers = new Dictionary<string, string>()
{
{"Arthur", "808-567-1543"},
{"Betty", "808-291-9838"},
{"Charles", "808-521-0129"},
{"Debbie", "808-317-3918"},
};
The foreach
statement enables you to iterate over the objects in a collection. C# also enables you to write your own iterators to yield a sequence of results.
To make an iterator, create a method that returns IEnumerable
or a generic type such as IEnumerable<String>
. Make the method generate its values and use a yield return
statement to return them to the code that is looping over the iteration.
The following iterator yields a list of prime numbers between startNumber
and stopNumber
.
// Enumerate prime numbers between startNumber and stopNumber.
public IEnumerable Primes(int startNumber, int stopNumber)
{
// Define a lambda expression that tests primality.
Func<int, bool> isPrime = x =>
{
if (x == 1) return false; // 1 is not prime.
if (x == 2) return true; // 2 is prime.
if (x % 2 == 0) return false; // Even numbers are not prime.
for (int i = 3; i * i <= x; i += 2)
if (x % i == 0) return false;
return true;
};
for (int i = startNumber; i <= stopNumber; i++)
{
// If this number is prime, enumerate it.
if (isPrime(i)) yield return i;
}
}
This code first makes a lambda expression that returns true
if a number is prime. It then loops through the values between startNumber
and stopNumber
and uses a yield return
statement for those that are prime.
The following code loops through the values yielded by the Primes
iterator and displays them in a ListBox
.
foreach (int i in Primes(1, 100)) primesListBox.Items.Add(i);
3.129.217.194