Collections

Arrays are the most popular kind of collection. However, the .NET FCL offers a variety of other collections with different semantics. Collections are abstractions of data algorithms. ArrayList abstracts a dynamic array; the Stack collection abstracts a stack data structure; the Queue collection abstracts queues; the Hashtable collection abstracts a lookup table; and so on. Each collection exposes both unique and standard interfaces. The unique interface is specific to the collection type. For example, the Stack type has pop and push methods, whereas the Queue type has Dequeue and Enqueue methods. In addition, collections implement the ICollection, IEnumerable, and ICloneable interfaces. (These interfaces were described earlier in this chapter in separate sections specific to each interface.) The non-generic collection classes are implemented in the System.Collections namespace. For similar solutions to arrays, lists, and dictionaries, generic collections are preferred to non-generic and are implemented in System.Collections.Generic. Generics are detailed in Chapter 7.

Table 5-5 lists the non-generic collections in the .NET FCL.

Table 5-5. Collection types

Class

Description

ArrayList

Dynamic array

BitArray

Bit array

Hashtable

Lookup table of keys and values

Queue

First-in/first-out (FIFO) collection of elements

SortedList

Sorted list of elements

Stack

Last-in/first-out (LIFO) collection of elements

What follows is a detailed explanation of each collection found in the Collections namespace. The explanations are complemented with sample code that highlights the uniqueness and strength of each collection. In addition to the listed member functions, many of the collections also support these extension methods: Queryable.AsQueryable, Enumerable.Cast, and Enumerable.OfType. These extension methods are explained in Chapter 7.

ArrayList Collection

An array list is a dynamic array. While a conventional array has a fixed number of elements, elements can be added or deleted at run time with a dynamic array. ArrayList elements are accessible using the indexing operator and indices.

In addition to the standard collection interfaces, ArrayList also implements the IList interface.

Table 5-6 lists the ArrayList-specific methods and properties. The static members of ArrayList are thread-safe, whereas instance members are not.

Table 5-6. ArrayList members

Member

Syntax

Constructor

The ArrayList constructor is overloaded. These are the overloaded constructors.

ArrayList()
ArrayList(
    ICollection sourceCollection)
ArrayList(int capacity)

Adapter

This method creates a wrapper ArrayList from an IList collection.

static ArrayList Adapter(
    IList list)

Add

This method adds an element to the end of the ArrayList collection.

virtual int Add(object value)

AddRange

This method adds a range of elements to the ArrayList collection. The additional elements are received from any type that implements the ICollection interface.

virtual void AddRange(
    ICollection elements)

BinarySearch

This method performs a binary search for a specific value in a sorted ArrayList collection. The sort is controlled by the IComparable interface.

virtual int BinarySearch(
    object value)
virtual int BinarySearch(
    object value,
    IComparer comparer)
virtual int BinarySearch(
    int index,
    int count,
    object value,
    IComparer comparer)

Capacity

This property gets or sets the number of elements allowed in the collection. Capacity is different from the actual number of elements. The capacity is the number of elements the ArrayList can store. The capacity is increased automatically as elements are added. When the number of elements exceeds the current capacity, the capacity doubles. You can use the capacity to improve the memory management of elements in a collection.

virtual int Capacity {
    get; set; }

Clear

This method removes all the elements of the collection.

virtual void Clear()

Contains

This method returns true if the specified element is found in a collection. If the element is not found, it returns false.

virtual bool Contains(object item)

Count

This property returns the number of elements in the collection.

virtual int Count {
    get; }

FixedSize

This method returns a fixed-sized version of the collection parameter.

static ArrayList FixedSize(
    ArrayList sourceArray)
static IList FixedSize(
    IList sourceList)

GetRange

This method returns a span of elements from the current array list. The result is returned as an ArrayList.

virtual ArrayList GetRange(
    int index, int count)

IndexOf

This method returns the index of the first matching element in the collection.

virtual int IndexOf(
    object value)
virtual int IndexOf(object value,
    int startIndex)
virtual int IndexOf(object value,
   int startIndex,
   int count)

Insert

This method inserts an element into the collection at the specified index.

virtual void Insert(int index,
    object value)

InsertRange

This method inserts multiple elements into the collection at the specified index.

virtual void InsertRange(
    int index,
    ICollection sourceCollection)

IsFixedSize

This property returns true if the collection is of fixed length. Otherwise, the property returns false.

virtual bool IsFixedSize {
    get; }

IsReadOnly

This property returns true if the collection is read-only. Otherwise, the property returns false.

virtual bool IsReadOnly {
    get; }

Item

This property gets or sets the value of the element at the index.

virtual object this[int index] {
   get; set; }

LastIndexOf

This method returns the index of the last matching element in the collection.

virtual int LastIndex(
    object value)
virtual int LastIndexOf(object value,
    int startIndex)
virtual int LastIndexOf(object value,
   int startIndex,
   int count)

ReadOnly

This method creates a read-only wrapper for an IList object.

static ArrayList ReadOnly(
    ArrayList sourceArray)
static IList ReadOnly(
    IList sourceList)

Remove

This method removes the first element in the collection that matches the value.

virtual void Remove(
    object value)

RemoveAt

At the specified index, this method removes the element from the collection.

virtual void RemoveAt(
    int index)

RemoveRange

This method removes a range of elements from a collection.

virtual void RemoveRange(
    int index,
    int count)

Repeat

This method returns an ArrayList with each element initialized to the specified value. Count is the number of elements in the returned ArrayList.

static ArrayList Repeat(
    object value,
    int count)

Reverse

This method reverses the order of elements in the collection.

virtual void Reverse()
virtual void Reverse(
    int beginIndex,
    int endingIndex)

SetRange

This method copies elements from the source collection over the same elements in the current collection. The copy starts at the index.

virtual void SetRange(
    int index,
    ICollection sourceCollection)

Sort

This method sorts an ArrayList. The sort is controlled by the IComparable interface of the element types.

virtual void Sort()
virtual void Sort(
    IComparer comparer)
virtual void Sort(int index,
    int count,
    IComparer comparer)

Synchronized

This method returns a thread-safe wrapper of an ArrayList or IList object.

static ArrayList Synchronized(
    ArrayList sourceArray)
static IList Synchronized(
    IList sourceList)

ToArray

This method copies the current array. The Type parameter specifies the target type of the array.

virtual object [] ToArray()
virtual Array ToArray(Type type)

TrimToSize

This method sets the capacity to the number of elements in the collection.

virtual void TrimToSize()

IEnumerable members

GetEnumerator

ICloneable members

Clone

ICollection members

CopyTo, Count, IsSynchronized, and SyncRoot

The following code uses some ArrayList methods and properties. It creates a new ArrayList. Elements then are added from command-line arguments. The command-line arguments should be integer values. Then the values of the elements in the cloned ArrayList are doubled. Afterward, the cloned ArrayList is enumerated and every element is displayed:

using System;
using System.Collections;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main(string [] argv) {

            ArrayList al1 = new ArrayList();
            foreach(string arg in argv) {
                al1.Add(int.Parse(arg));
            }
            al1.Sort();
            ArrayList al2 = (ArrayList)al1.Clone();
            for (int count = 0; count < al2.Count; ++count) {
                al2[count] = ((int)al2[count]) * 2;
            }
            foreach (int number in al2) {
                Console.WriteLine(number);
            }
        }
    }
}

BitArray Collection

The BitArray collection is a composite of bit values. Bit values are 1 and 0, where 1 is true and 0 is false. This collection provides an efficient means of storing and retrieving bit values.

Table 5-7 lists the methods and properties specific to a BitArray collection. The static members of the BitArray are thread-safe, whereas instance members are not.

Table 5-7. BitArray members

Member

Syntax

Constructor

The BitArray constructor is overloaded. These are some of the overloaded constructors.

BitArray(bool [] bits)
BitArray(int [] bits)
BitArray(int count,
    bool default)

And

This method performs a bitwise AND on the current instance and the BitArray parameter. The result is the returned BitArray.

BitArray And(BitArray value)

Get

This method returns a specific bit in the BitArray collection.

bool Get(int index)

IsReadOnly

This property returns true if the collection is read-only. Otherwise, the property returns false.

virtual bool IsReadOnly {
    get; }

Item

This property gets or sets the bit at the index.

virtual object this[int index] {
    get; set; }

Length

This property gets or sets the number of bits in the collection.

public int Length {
    get; set; }

Not

This method negates the bits of the BitArray collection. The result is the returned BitArray.

BitArray Not()

Or

This method performs a bitwise OR on two BitArray collections, the current instance and the parameter. The result is in the returned BitArray.

BitArray Or(BitArray value)

Set

This method sets a specific bit in the collection.

void Set(int index, bool value)

SetAll

This method sets all the bits of the collection to true or false.

void SetAll(bool value)

Xor

This method performs an exclusive OR on the current instance and the BitArray parameter.

BitArray Xor(
    BitArray value)

IEnumerable member

GetEnumerator

ICloneable members

Clone

ICollection members

CopyTo, Count, IsSynchronized, and SyncRoot

The following code demonstrates the BitArray collection. The Employee class contains a BitArray collection that tracks employee enrollment in various programs, such as the health plan and the credit union. This is convenient because program enrollment is always either true or false. In the Employee class, properties are provided to set and get enrollment in various programs:

using System;
using System.Collections;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            Employee ben = new Employee();
            ben.InProfitSharing = false;
            ben.InHealthPlan = false;
            Employee valerie = new Employee();
            valerie.InProfitSharing = false;
            Participation("Ben", ben);
            Participation("Valerie", valerie);
        }

        public static void Participation(string name, Employee person) {
            Console.WriteLine(name + ":");
            if (person.InProfitSharing) {
                Console.WriteLine("   Participating in" +
                    " Profit Sharing");
            }
            if (person.InHealthPlan) {
                Console.WriteLine("   Participating in" +
                    " Health Plan");
            }
            if (person.InCreditUnion) {
                Console.WriteLine("   Participating in" +
                    " Credit Union");
            }
        }
    }

    public class Employee {
        public Employee() {
            eflags.SetAll(true);
        }

        private BitArray eflags = new BitArray(3);

        public bool InProfitSharing {
            set {
                eflags.Set(0, value);
            }
            get {
                return eflags.Get(0);
            }
        }

        public bool InHealthPlan {
            set {
                eflags.Set(1, value);
            }
            get {
                return eflags.Get(1);
            }
        }

        public bool InCreditUnion {
            set {
                eflags.Set(2, value);
            }
            get {
                return eflags.Get(2);
            }
        }
    }
}

Hashtable Collection

The Hashtable collection is a collection of key/value pairs. Entries in this collection are instances of the DictionaryEntry type. DictionaryEntry types have a Key and Value property to get and set keys and values.

In addition to the standard collection interfaces, the Hashtable collection implements the IDictionary, ISerializable, and IDeserializationCallback interfaces.

The entries are stored and retrieved in order based on the hash code contained in the key.

Table 5-8 lists the members of the Hashtable collection.

Table 5-8. Hashtable members

Member

Syntax

Constructor

The Hashtable constructor is overloaded. This is the syntax of some of the overloaded constructors.

Hashtable()
Hashtable(int capacity)
Hashtable(int capacity,
    float loadFactor)

Add

This method adds an element to the collection.

virtual void Add(object key,
    object value)

Clear

This method deletes all elements in the collection.

virtual void Clear()

Contains

This method returns true if the key is found in the collection. If the key is not present, the method returns false.

virtual bool Contains(
    object key)

ContainsKey

This method returns true if the key is found in the collection. If the key is not present, it returns false. Identical to the Contains method.

virtual bool ContainsKey(
    object key)

ContainsValue

This method returns true if the value is found in the collection. If the value is not present, the method returns false.

virtual bool ContainsValue(
    object value)

GetEnumerator

This method returns an IDictionaryEnumerator object, which can be used to enumerate the elements of the hashtable.

virtual IDictionaryEnumerator
    GetEnumerator()

GetHash

This method returns the hash code for the specified key.

virtual int GetHash(
    object key)

GetObjectData

This method serializes the hashtable collection.

virtual void GetObjectData(
    SerializationInfo info,
    StreamingContext context)

IsFixedSize

This property returns true if the collection is of fixed size. Otherwise, it returns false.

virtual bool IsFixedSize {
    get; }

IsReadOnly

This property returns true if the collection is read-only. Otherwise, it returns false.

virtual bool IsReadOnly {
    get; }

IsSynchronized

This property returns true if the collection is synchronized.

virtual bool IsSynchronized {
    get; }

Item

This property gets or sets a value pertaining to a key.

virtual object this[object key] {
    get; set; }

KeyEquals

This method compares a key to a value. If they are equal, true is returned; if not, false is returned. This method is used primarily to compare two keys.

virtual bool KeyEquals(
    object item,
    object key)

Keys

This method returns a collection that contains the keys of the hashtable.

virtual ICollection Keys {
    get; }

OnDeserialization

This method is called when deserialization is completed.

virtual void OnDeserialization(
    object sender)

Remove

This method removes an element of the specified key from the collection.

virtual void Remove(
    object key)

Synchronized

This method returns a thread-safe wrapper of the collection.

static Hashtable Synchronized(
    Hashtable sourceTable)

Values

This property returns a collection that has the values of the hashtable.

virtual ICollection Values {
    get; }

IEnumerable members

GetEnumerator

ICloneable members

Clone

ICollection members

CopyTo, Count, IsSynchronized, and SyncRoot

Hashtable.GetEnumerator implements IDictionary.GetEnumerator, which returns an IDictionaryEnumerator. IDictionaryEnumerator implements the IEnumerator interface, while also adding three properties: Entry, Key, and Value.

The following code extends the previous sample code for the BitArray collection. The program creates a Hashtable, where each element is an employee. The key is the employee ID, and the value is an instance of an Employee type:

using System;
using System.Collections;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            Hashtable employees = new Hashtable();
            employees.Add("A100", new Employee(
                "Ben", true, false, true));
            employees.Add("V100", new Employee(
                "Valerie", false, false, true));
            Participation((Employee) employees["A100"]);
            Participation((Employee) employees["V100"]);
        }

        public static void Participation(Employee person) {
            Console.WriteLine(person.Name + ":");
            if (person.InProfitSharing) {
                Console.WriteLine("   Participating in" +
                    " Profit Sharing");
            }
            if (person.InHealthPlan) {
                Console.WriteLine("   Participating in" +
                    " Health Plan");
            }
            if (person.InCreditUnion) {
                Console.WriteLine("   Participating in" +
                    " Credit Union");
            }
        }
    }

    public class Employee {

        public Employee(string emplName) {
            propName = emplName;
            eflags.SetAll(true);
        }

        public Employee(string emplName,
                        bool profitSharing,
                        bool healthPlan,
                        bool creditUnion) {
            propName = emplName;
            InProfitSharing = profitSharing;
            InHealthPlan = healthPlan;
            InCreditUnion = creditUnion;
        }

        private BitArray eflags = new BitArray(3);

        public bool InProfitSharing {
            set {
                eflags.Set(0, value);
            }
            get {
                return eflags.Get(0);
            }
        }

        public bool InHealthPlan {
            set {
                eflags.Set(1, value);
            }
            get {
                return eflags.Get(1);
            }
        }

        public bool InCreditUnion {
            set {
                eflags.Set(2, value);
            }
            get {
                return eflags.Get(2);
            }
        }

        private string propName;
        public string Name {
            get {
                return propName;
            }
        }
    }
}

This is sample code that shows the use of an IDictionaryEnumerator enumerator:

using System;
using System.Collections;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            Hashtable zHash = new Hashtable();
            zHash.Add("one", 1);
            zHash.Add("two", 2);
            zHash.Add("three", 3);
            zHash.Add("four", 4);
            IDictionaryEnumerator e =
                zHash.GetEnumerator();
            while (e.MoveNext()) {
                Console.WriteLine(
                    "{0} {1}",
                    e.Key, e.Value);
            }
        }
    }
}

Queue Collection

A Queue collection abstracts a FIFO data structure. Queue collections are ideal for implementing messaging components.

Table 5-9 lists the members of the Queue collection.

Table 5-9. Queue members

Member

Syntax

Constructor

The Queue constructor is overloaded. This is the syntax of the overloaded constructors.

public Queue()
public Queue(
    ICollection sourceCollection)
public Queue(int capacity)
public Queue(int capacity,
    float factor)

Clear

This method removes all the elements of the collection.

virtual void Clear()

Contains

This method returns true if the specified value is found in the collection. If the value is not found, the method returns false.

virtual bool Contains(object value)

Dequeue

This method removes and returns the first element on the queue.

virtual object Dequeue()

Enqueue

This method adds an element to the queue.

virtual void Enqueue(
    object element)

Peek

This method returns the first element of the queue without removing it.

virtual object Peek()

Synchronized

This method returns a thread-safe wrapper for a queue object.

static Queue Synchronized(
    Queue sourceQueue)

ToArray

This method creates a new array from the elements of the queue.

virtual object[] ToArray()

TrimToSize

This method sets the capacity to the number of elements in the collection.

virtual void TrimToSize()

IEnumerable members

GetEnumerator

ICloneable members

Clone

ICollection members

CopyTo, Count, IsSynchronized, and SyncRoot

This is sample code of the Queue collection. Customers are added to the queue and then displayed:

using System;
using System.Collections;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            Queue waiting = new Queue();
            waiting.Enqueue(new Customer("Bob"));
            waiting.Enqueue(new Customer("Ted"));
            waiting.Enqueue(new Customer("Kim"));
            waiting.Enqueue(new Customer("Sam"));

            while (waiting.Count != 0) {
                Customer cust =
                    (Customer) waiting.Dequeue();
                Console.WriteLine(cust.Name);
            }
        }

        public class Customer {
            public Customer(string cName) {
                propName = cName;
            }

            private string propName;
            public string Name {
                get {
                    return propName;
                }
            }
        }
    }
}

SortedList

The SortedList collection is a combination of key/value entries and an ArrayList collection, where the collection is sorted by the key. Elements of the collection are accessible either through the key or through an index.

Table 5-10 includes the members of the SortedList collection.

Table 5-10. SortedList members

Member

Syntax

Constructor

The SortedList constructor is overloaded. These are some of the overloaded constructors.

SortedList()
SortedList(IComparer comparer)
SortedList(
    IDictionary sourceCollection)

Add

This method adds an element to the collection.

virtual void Add(object key,
    object value)

Capacity

This property gets or sets the capacity of the collection.

virtual int Capacity {
    get; set; }

Clear

This method removes all the elements of the collection.

virtual void Clear()

Contains

This method returns true if the specified value is found in the collection. If the value is not found, the method returns false.

virtual bool Contains(object value)

ContainsKey

This method returns true if the key is found in the collection. If the key is not present, it returns false. Identical to the Contains method.

virtual bool ContainsKey(
    object key)

ContainsValue

This method returns true if the value is found in the collection. If the value is not present, it returns false.

virtual bool ContainsValue(
    object value)

GetByIndex

This method returns the value at the specified index.

virtual object GetByIndex(
    int index)

GetKey

This method returns the key at the specified index.

virtual object GetKey(
    int index)

GetKeyList

This method returns all the keys of the collection in a list.

virtual IList GetKeyList()

GetValueList

This method returns all the values of the SortedList in a new list.

virtual IList GetValueList()

IndexOfKey

This method returns the index of a key found in the collection. If not found, -1 is returned.

virtual int IndexOfKey(
    object key)

IndexOfValue

This method returns the index to the first instance of this value in the collection.

virtual int IndexOfValue(
    object value)

IsFixedSize

This property returns true if the collection is of fixed size. Otherwise, it returns false.

virtual bool IsFixedSize {
    get; }

IsReadOnly

This property returns true if the collection is read-only. Otherwise, it returns false.

virtual bool IsReadOnly {
    get; }

Item

This property gets or sets the value of this key.

virtual object this[object key] {
    get; set; }

Keys

This property returns the keys of the SortedList in a collection.

public virtual ICollection Keys {
    get; }

Remove

This method removes the element identified by the key from the collection.

virtual void Remove(
    object key)

RemoveAt

This method removes the element at the specified index.

virtual void RemoveAt(
    int index)

SetByIndex

This method sets the value of the element at the specified index.

virtual void SetByIndex(
    int index, object value)

Synchronized

This method returns a thread-safe wrapper for a SortedList object.

static SortedList Synchronized(
    SortedList sourceList)

TrimToSize

This method trims the capacity to the actual number of elements in the collection.

virtual void TrimToSize()

Values

This property returns the values in a collection.

virtual ICollection Values {
    get; }

IEnumerable members

GetEnumerator

ICloneable members

Clone

ICollection members

CopyTo, Count, IsSynchronized, and SyncRoot

The following program is an application that tracks auto repair tickets. Each ticket, which is an instance of the AutoRepairTicket class, is added to a sorted list. The key is the customer name. The value is the actual ticket. After populating the SortedList type, the CustomerReport method lists the open tickets:

using System;
using System.Collections;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            SortedList tickets = new SortedList();
            AutoRepairTicket ticket = NewTicket("Ben");
            tickets.Add(ticket.Name, ticket);
            ticket = NewTicket("Donis");
            tickets.Add(ticket.Name, ticket);
            ticket = NewTicket("Adam");
            tickets.Add(ticket.Name, ticket);
            CustomerReport(tickets);
        }

        public static AutoRepairTicket NewTicket(
                string customerName) {
            return new AutoRepairTicket(customerName,
                DateTime.Now);
        }

        public static void CustomerReport(SortedList list) {
            foreach (DictionaryEntry entry in list) {
                int nextTag = ((AutoRepairTicket) entry.Value).Tag;
                string nextTime = ((AutoRepairTicket)
                    entry.Value).Time.ToShortTimeString();
                Console.WriteLine("Customer: {0} Ticket: {1} Time: {2}",
                    entry.Key, nextTag, nextTime);
            }
        }
    }

    public class AutoRepairTicket{
        public AutoRepairTicket(string customerName,
                DateTime ticketTime) {
            propName = customerName;
            propTime = ticketTime;
            propTag = ++count;
        }

        private string propName;
        public string Name {
            get {
                return propName;
            }
        }

        private DateTime propTime;
        public DateTime Time {
            get {
                return propTime;
            }
        }

        private int propTag;
        public int Tag {
            get {
                return propTag;
            }
        }

        private static int count = 1000;
    }
}

Stack Collection

A Stack collection abstracts a LIFO data structure.

Table 5-11 lists the members of the Stack collection.

Table 5-11. Stack members

Member

Syntax

Clear

This method removes all the elements of the collection.

virtual void Clear()

Contains

This method returns true if the specified value is found in the collection. If the value is not found, the method returns false.

virtual bool Contains(object value)

Peek

This method previews the most recent element on the stack. The element is returned without removing it from the stack.

virtual object Peek()

Pop

This method returns and removes the top element of the stack.

virtual object Pop()

Push

This method pushes an element onto the stack.

virtual void Push(object obj)

Synchronized

This method returns a thread-safe wrapper for the Stack collection.

static Stack Synchronized(
    Stack sourceStack)

ToArray

This method returns the elements of the Stack collection as a regular array.

virtual object[] ToArray()

The following code adds numbers to a Stack collection. The values of the elements in the collection are removed from the stack and then displayed to the Console window:

using System;
using System.Collections;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            Stack numbers = new Stack(
                new int[] {1,2,3,4,5,6});
            int total = numbers.Count;
            for (int count = 0; count < total; ++count) {
                Console.WriteLine(numbers.Pop());
            }
        }
    }
}

Specialized Collections

In addition to the common collections that most developers use, the .NET FCL offers specialized collections. These collections are found in the System.Collections.Specialized namespace. Although these collections are used infrequently, they are valuable in certain circumstances.

Table 5-12 lists the specialized collections.

Table 5-12. Specialized collections in the .NET FCL

Member

Description

BitVector32

This is an array of 32 bits. It is similar to a BitArray, but it is limited to 32 bits. Because of this array’s refined use, BitVector32 structures are more efficient than a BitArray collection.

HybridDictionary

This collection is a combination of a ListDictionary and a Hashtable. It operates as a ListDictionary when it contains a small number of elements. For optimum performance, the collection switches to a Hashtable as the number of elements increases.

NameValueCollection

This is a collection of keys and values, in which both the keys and values are strings. The collection is accessible via an index or key. A key can refer to multiple values.

OrderedDictionary

This is a collection of key and value pairs, where each entry is accessible by either the key or the value.

StringCollection

This is a collection of strings.

StringDictionary

This is a combination of the Hashtable and StringCollection collections, in which both the keys and values are strings.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.232.239