- C# 6 and .NET Core 1.0:Modern Cross:Platform Development
- Mark J. Price
- 1305字
- 2025-04-04 20:07:42
Storing data with collections
If you need to store multiple values, you can use a collection. A collection is a data structure in memory that can manage multiple items in different ways, although all collections have some shared functionality.
There are two main namespaces for collections:
System.Collections
: Avoid the types in this namespace because they store any type that derives fromSystem.Object
, that is, every type (which is flexible but not type safe, thus leading to errors and boxing of value types, which can be slow and inefficient).System.Collections.Generic
: The types in this namespace were introduced in C# 2 with .NET 2.0 and are better because they allow you to specify the type you want to store (which is safer, faster, and more efficient).
All collections have a Count
property to tell you how many items are in it. For example, if we had a collection named passengers
we could do this:
int howMany = passengers.Count;
All collections can be iterated using the foreach
statement. To perform some action on all the items in the passengers
collection, we can do this:
foreach (var passenger in passengers) { // do something with each passenger }
Understanding collections
There are several different collection categories: lists, dictionaries, stacks, queues, sets, and many other more specialized collections.
Lists
Lists are best when you want to manually control the order of items in a collection. Each item in a list has a unique index (or position) that is automatically assigned. Items can be any type (although they should all be the same type) and items can be duplicated. Indexes are int
types and start from 0, so the first item in a list is at index 0, as shown in the following table:

If a new item (for example, Santiago) is inserted between London and Sydney, the index of Sydney is automatically incremented. Therefore, you must be aware that an item's index can change after inserting or removing items, as shown in the following table:

Dictionaries
Dictionaries are best when each value (or item) has a unique subvalue (or a made-up value) that can be used as a key to quickly find the value in the collection later on. The key must be unique. If you are storing a list of people, you can use a government-issued identity number as the key.
Think of the key as being like an index entry in a real-world dictionary. It allows you to quickly find the definition of a word because the words (that is, keys) are kept sorted, and if we know we're looking for the definition of Manatee, we would jump to the middle of the dictionary to start looking, because the letter M is in the middle of the alphabet. Dictionaries in programming are similarly optimized when looking something up.
Both the key and the value can be any type. This example uses strings for both:

Stacks
Stacks are best when you want to implement the last-in, first-out (LIFO) behavior. With a stack, you can only directly access the one item at the top of the stack, although you can enumerate to read through the whole stack of items. You cannot, for example, access the second item in a stack.
For example, word processors use a stack to remember the sequence of actions you have recently performed, so that when you press Ctrl + Z, it will undo the last action in the stack, and then the next last action, and so on.
Queues
Queues are best when you want to implement the first-in, first out (FIFO) behavior. With a queue you can only directly access the one item at the front of the queue, although you can enumerate to read through the whole queue of items. You cannot, for example, access the second item in a queue.
For example, background processes use a queue to process work items in the order that they arrive, just like people standing in line at the post office.
Sets
Sets are best when you want to perform set operations between two collections. For example, you may have two collections of city names and you want to know which names appear in both sets (known as the intersect between the sets).
Working with lists
Add a new console application project named Ch04_Lists.
In the Main
method, type the following code, which illustrates some of the common ways of working with lists:
var cities = new List<string>(); cities.Add("London"); cities.Add("Paris"); cities.Add("Milan"); WriteLine("Initial list"); foreach (string city in cities) { WriteLine($" {city}"); } WriteLine($"The first city is {cities[0]}."); WriteLine($"The last city is {cities[cities.Count - 1]}."); cities.Insert(0, "Sydney"); WriteLine("After inserting Sydney at index 0"); foreach (string city in cities) { WriteLine($" {city}"); } cities.RemoveAt(1); cities.Remove("Milan"); WriteLine("After removing two cities"); foreach (string city in cities) { WriteLine($" {city}"); }
Tip
The angle brackets after the List<T>
type are a feature of C# called generics. It's just a fancy term for making a collection strongly typed, that is, the compiler knows more specifically what type of object is allowed to be stored in the collection. Generics improve the performance and correctness of your code. Strongly typed collections are different from statically typed collections. The old System.Collection
types are statically typed to contain weakly typed System.Object
items. The newer System.Collection.Generic
types are statically typed to contain strongly typed <T>
instances. Ironically, the term "generics" just means a more specific static type!
Press Ctrl + F5 to see the output:
Initial list London Paris Milan The first city is London. The last city is Milan. After inserting Sydney at index 0 Sydney London Paris Milan After removing two cities Sydney Paris
Working with dictionaries
Add a new console application project named Ch04_Dictionaries.
In the Main
method, type the following code that illustrates some of the common ways of working with dictionaries:
var keywords = new Dictionary<string, string>(); keywords.Add("int", "32-bit integer data type"); keywords.Add("long", "64-bit integer data type"); keywords.Add("float", "Single precision floating point number"); WriteLine("Keywords and their definitions"); foreach (KeyValuePair<string, string> item in keywords) { WriteLine($" {item.Key}: {item.Value}"); } WriteLine($"The definition of long is {keywords["long"]}");
Run the application by pressing Ctrl + F5.
Keywords and their definitions int: 32-bit integer data type long: 64-bit integer data type float: Single precision floating point number The definition of long is 64-bit integer data type
Sorting collections
A List<T>
class can be sorted by calling its Sort
method (but remember that the indexes of each item will change).
Tip
Sorting a list of strings or other built-in types works automatically, but if you create a collection of your own type, then that type must implement an interface named IComparable
. You will learn how to do this in Chapter 7, Implementing Interfaces and Inheriting Classes.
The Dictionary<T>
, Stack<T>
, or Queue<T>
classes cannot be sorted, because you wouldn't usually want that functionality. For example, you would never sort a queue of guests checking into a hotel. But sometimes, you might want to sort a dictionary or a set.
The differences between these sorted collections are often subtle, but can have an impact on the memory requirements and performance of your application, so it is worth putting some effort into picking the best for your requirements. The following table summarizes some examples of sorted collection:

Avoiding old collections
Avoid the old collections, listed in the following table, and use the more modern equivalents instead.
In 2005, Microsoft introduced generics that can be used to control more specifically which types can be stored in a collection. A collection that can only contain the int
types is safer than one that can contain any object. The <T>
parameter should be replaced with the type you want to store.

Using specialized collections
There are a few other collections for special situations. For example, the NameValueCollection
can be used to automate filling in a form on a web page and posting the named values to the web server:
